Почему вычисления с использованием real дают результаты, отличные от вычисления с использованием int? - PullRequest
1 голос
/ 08 сентября 2011

У меня есть такой код, например:

(a) writeln ('real => ', exp(3*Ln(3)):0:0);  // return 27
(b) writeln ('int => ', int(exp(3*Ln(3))):0:0); // return 26

Это ошибка?Функция calc 3 ^ 3 (экспонента использует функции ln и exp), но преобразование из действительного в int завершается неудачно;в случае (a) верните 27, в случае (b) верните (26), когда должно быть 27 оба.Как я могу это решить?Спасибо за помощь

Ответы [ 5 ]

9 голосов
/ 08 сентября 2011

Нет, это не ошибка. Компьютеры просто не имеют бесконечной точности, поэтому результат будет не точно 27, а, возможно, 26.999999999 или что-то в этом роде. И поэтому, когда вы int или trunc это, оно заканчивается как 26. Используйте Round вместо.

6 голосов
/ 08 сентября 2011

Из-за обычных ошибок с плавающей точкой выражение, которое вы печатаете, оценивается в чуть меньше 27.Компьютер не может точно представить натуральный логарифм 3, поэтому любые дальнейшие вычисления на его основе также будут иметь ошибки.

В комментариях вы заявляете, что exp (3 * ln (3)) = 27.000, но вы 'Мы не показали никаких программных доказательств этого утверждения.Ваш код говорит, что exp (3 * ln (3)) = 27, что менее точно.Он печатает это, потому что вы явно сказали WriteLn использовать меньшую точность. Часть :0:0 - это не просто украшение. Это означает, что вы хотите напечатать результат с нулевым десятичным разрядом.Когда вы говорите WriteLn сделать это, он округляет до такого количества десятичных разрядов.В этом случае округляется до .Но когда вы вводите вызов на Int, вы усекаете почти 27 значение ровно до 26, а затем WriteLn тривиально округляет его до 26 перед его печатью.

Если выскажите WriteLn, чтобы отобразить больше десятичных знаков, вы должны увидеть разные результаты.Обратитесь к документации для Write, чтобы узнать, что означают числа после двоеточий.

2 голосов
/ 08 сентября 2011

Работа с плавающей точкой не всегда дает 100% точный результат.Причина в том, что двоичная переменная с плавающей запятой не всегда может точно представлять значения.То же самое относится и к десятичным числам.Если вы возьмете 1/3, в 6-значной десятичной точности, будет 0,333333.Тогда если вы возьмете 0,333333 * 3 = 0,999999.Int (0.999999) = 0

Вот несколько слов об этом ...

Что должен знать каждый компьютерный специалист об арифметике с плавающей точкой

1 голос
/ 08 сентября 2011

Вы также должны взглянуть на статью Руди Велтуиса:

http://rvelthuis.de/articles/articles-floats.html

0 голосов
/ 08 сентября 2011

Не ошибка.Это просто еще один пример того, как плавающая арифметика работает на компьютере.Арифметика с плавающей точкой является лишь приближением того, как действительные числа работают в математикеНет и не может быть гарантии, что результаты с плавающей запятой будут бесконечно точными.Фактически, вы должны ожидать, что они почти всегда будут в какой-то степени неточными.

...