Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Object Pascal: кроссплатформенные технологии > Ошибка при умножении чисел


Автор: Julius 10.1.2010, 13:29
Уважаемые программисты) нужна ваша помощь. При написании программы столкнулся с проблемой, суть выписал вниз: 

Код

var a, b, c: byte;
n: longint;
begin
writeln(37*41*61);
a:=37;
b:=41;
c:=61;
n:= a*b*c;
writeln(n);
end.


Выводит:
Цитата

92537
27001


т.е. прямо в операторе умножать - хорошо(37*41*61 действительно равно 92537), а переменная записывается с ошибкой. В чем проблема?


UP: по совету приятеля решено заменой типа a,b,c на longint, правда суть ошибки я так и не понял)
UP: после второго поста Фантома понял суть)

Автор: Фантом 10.1.2010, 14:13
Цитата(Julius @  10.1.2010,  13:29 Найти цитируемый пост)

т.е. прямо в операторе умножать - хорошо(37*41*61 действительно равно 92537), а переменная записывается с ошибкой. В чем проблема? 

В типе переменных a,b,c и в особенностях автоприведения типов у Паскаля. При умножении a*b*c результату "по умолчанию" приписывается тип integer, но реальный результат выходит за пределы возможных значений для этого типа, и в итоге два старших бита отбрасываются. В том же случае, когда Вы умножаете числа прямо в writeln, операндам приписывается тип integer, а не byte.

Автор: ТоляМБА 10.1.2010, 14:19
Цитата(Фантом @  10.1.2010,  16:13 Найти цитируемый пост)
операндам приписывается тип integer
И что? У Integer верхний диапазон 32767, а 92537 как бы побольше будет.

Автор: Julius 10.1.2010, 14:19
Фантом, спасибо, уже потом увидел ваше сообщение) правда integer тут действительно ни при чем, да и впрочем у меня тип "n" longint а не integer.

Автор: Фантом 10.1.2010, 15:38
Цитата(ТоляМБА @  10.1.2010,  14:19 Найти цитируемый пост)
И что? У Integer верхний диапазон 32767, а 92537 как бы побольше будет.

Насколько я помню, Turbo Pascal при арифметических операциях допускает возможность выхода за границы типа, увеличивая размер типа результата на "следующий": до integer при работе с byte и до longint при работе с integer. В этом и дело - результаты умножения byte в integer не влезают, а вот результаты уможнения integer в longint помещаются.

Цитата(Julius @  10.1.2010,  14:19 Найти цитируемый пост)
да и впрочем у меня тип "n" longint а не integer.

Это неважно. Сначала результат вычислений в правой части оператора присваивания получает какой-то тип на основе представлений компилятора о преобразовании типов (о которых я писал выше), а уже потом помещается в переменную. Т.е. в этом случае сначала производится умножение с результатом типа integer (причем происходит обрезка результата), а уже потом получившийся неправильный результат типа integer неявно конвертируется в longint при присваивании.

P.S. И, кстати, эта особенность - главная, пожалуй, проблема Паскаля вообще и компилятора TP в частности. Заложенное в язык неявное преобразование числовых типов, конечно, упрощает использование его как обучающего, но приводит, во-первых, к неприятным последствиям вроде обсуждаемого, и, во-вторых, к очень неэффективному результату компиляции всевозможных вычислений. 

Автор: Julius 10.1.2010, 19:05
спасибо за информацию) как наберу 100 постов (если наберу 100 постов) ) - поставлю плюс)

M
Rrader
Поставил

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)