Подтвердить что ты не робот

Почему результат RoundTo (87.285, -2) => 87.28

Я ожидал, что результатом будет 87.29. Я также попробовал SimpleRoundTo, но дал тот же результат.

В справочной системе также есть "странный" пример: мс-помощь://embarcadero.rs2010/vcl/Math.RoundTo.html

RoundTo(1.235, -2) => 1.24
RoundTo(1.245, -2) => 1.24 //???

Кто-нибудь знает, какая функция мне нужна, чтобы получить результат 87.29? Я имею в виду: если последняя цифрa > 5 округляется вверх, если < 5 раунд вниз. Как учили в школе:)

Я использую Delphi2010 и SetRoundMode(rmNearest). Я также пробовал с помощью rmTruncate. Значение 87.285 хранится в переменной double.

Также странно:

SimpleRoundTo(87.285, -2) => 87.29

но

x := 87.285; //double
SimpleRoundTo(x, -2) => 87.28
4b9b3361

Ответ 1

87.285 не является точно представимым, а ближайший двойной немного меньше.

Классическая ссылка на плавающую точку Что каждый компьютерный ученый должен знать о плавающей точке, Точечная арифметика.

Для расчетов на основе валюты, если это действительно так, вы должны использовать базовый номер 10, а не плавающий с базой 2. В Delphi это означает Currency.

Ответ 2

Точное значение 87.285 не представляется в качестве значения с плавающей запятой в Delphi. Страница на моем веб-сайте показывает, что это действительно так: Extended, Double и Single:

87.285 = + 87.28500 00000 00000 00333 06690 73875 46962 12708 95004 27246 09375
87.285 = + 87.28499 99999 99996 58939 48683 51519 10781 86035 15625
87.285 = + 87.28500 36621 09375

По умолчанию литералы с плавающей запятой в Delphi имеют тип Extended, и, как вы можете видеть, расширенная версия вашего номера немного выше 87.285, поэтому правильно, что округление до ближайшего раунда будет округлено. Но, как двойное, реальное число немного ниже. Поэтому вы получите ожидаемое число, если вы явно сохраните номер в переменной Double перед вызовом RoundTo. Существуют перегрузки этой функции для каждого из типов с плавающей запятой Delphi.