parser

Написать ответ на текущее сообщение

 

 
   команды управления поиском

kb: как аккуратно работать с числами с плавающей точкой

Александр Петросян (PAF) 09.12.2005 16:21 / 09.12.2005 16:23

судя по комментарию в коде
http://www.parser.ru/examples/int2str/

его автор не разобрался в ключевом моменте.
он столкнулся с проблемой и ничего о ней не написал на форум/мне.

смотрим на его комментарий:
# Если сделать $cop(^math:trunc(^math:frac($amount)*100))
# по непонятной мне причине $amount = 123.21 дает $cop = 20
дальше автор не ищет совета -- увидев проблему он ставит на неё сверху пепельницу:
$cop(^math:frac($amount)*100) # Копейки - два знака после запятой
так работать с числами с плавающей точкой нельзя.

все знают, что компьютеры работают не с десятичным представлением числа, а вовсе даже с двоичным.

иными словами внутри хранится не набор степеней десятки, а набор степеней двойки.

иными словами, в частности, после десятичной точки число собирается не из кусочков
0.1
0.01
0.001
а из кусочков
1/2
1/4
1/8

причём лишь с известной конечной точностью.

вот проблема лицом:
$f(123.86-123)
#вышеобъявленный микроскоп
^f.format[%.20f]]
в зависимости от реализации системных библиотек это число выведется по-разному:

intel/sparc solaris, linux
0.85999999999999943157
0.85999999999999943157

win32
0.85999999999999943000

видно, что по-разному подбиваются незначащие разряды.
но значащие 15 хранятся исправно:
0.859999999999999

в математике число
0.(9) << ноль целых, девять в периоде
это просто ещё одна запись числа
1 << один
они не отличаются ни на сколько.

поэтому числа с плавающей точкой всегда при выводе округляют (round).

объявляется конкурс на то, как правильно надо было написать это место в int2str.

мне вспоминается, что об этом уже тут писал.