?

Log in

No account? Create an account

Эффект двойного округления - Общество дровосеков Бердичева по изучению Мишны

Dec. 19th, 2014

03:34 pm - Эффект двойного округления

Previous Entry Share Next Entry

Как дополнительная точность влияет на результат одной-единственной операции с плавающей точкой.



Режим округления, как это принято по умолчанию — к ближайшему; если ничья, то к четному (tie break to even).

Значение 1/2731 равно (в 16-ричной записи мантиссы, т.е. в представлении формата %a)
0x1.7FF4005FFD0017FF4005FFD001(и т.д. 7FF4005FFD001 в периоде)...p-12
или, в десятичном виде,
3.6616623947272061515928231417...e-4

Результат типа double (53 бита мантиссы), полученный при делении с точностью double (напр. SSE2 на x86_64), будет
0x1.7FF4005FFD001p-12
3.66166239472720588e-4

так как старший бит отбрасываемой части - это старший бит красной 16-ричной цифры 7, т.е. 0.

Результат типа long double (64 бита мантиссы) будет
0x1.7FF4005FFD001800p-12
3.6616623947272061517e-4

(здесь самый младший бит 16-ричного числа 65-й по счету, и с него — с младшего бита красной цифры F, т.е. c 1 — начиналась отбрасываемая части, в которой есть еще биты, равные 1, поэтому округляем вверх).

Соответственно, результат типа double, сохраненный из полученного при делении с точностью long double, из-за округления синих 800 до младшей четной цифры в остающейся части мантиссы, будет
0x1.7FF4005FFD002p-12
3.66166239472720642e-4


Такие дела.

Comments:

[User Picture]
From:ramlamyammambam
Date:December 20th, 2014 01:59 am (UTC)
(Link)
Всякое двойное округление есть зло. :)
(Reply) (Thread)
[User Picture]
From:spamsink
Date:December 20th, 2014 02:11 am (UTC)
(Link)
Зато потом результат двойного округления, умноженный на 2731, дает (после округления вниз) ровно 1, а результат одинарного, после умножения, будучи по модулю меньше единицы, из-за нормализации на 1 бит влево нуждается для округления вверх во вдвое большей (по сравнению с первым) близости к значению 1, чего мы не имеем, оттого и получается округление вниз к результату, на единицу младшего разряда мантиссы отличному от единицы.

Edited at 2014-12-20 02:12 am (UTC)
(Reply) (Parent) (Thread)
[User Picture]
From:sab123
Date:December 20th, 2014 02:36 am (UTC)
(Link)
У меня от сравнений десятичных плавающих чисел осталось ощущение, что нужно округлять где-то как минимум два последних десятичных порядка. Что этот пример подтверждает. %15g (или 14? или 16? не помню, судя по этому примеру - 16), что-ли, дает удовлетворительно воспроизводимые результаты. А все, что дальше этой точности - то при переводе в двоичную форму и обратно съезжает в непонять что.
(Reply) (Thread)
[User Picture]
From:spamsink
Date:December 20th, 2014 03:09 am (UTC)
(Link)
Значащих десятичных цифр при двоичной мантиссе длиной N бит, считая скрытый, если есть, и двоичном порядке, будет floor((N-1)/log210), т.е. 15 для double и 6 для float (как %f и имеет в виду по умолчанию, на случай, если реально печатаются floats).
(Reply) (Parent) (Thread)
[User Picture]
From:sab123
Date:December 20th, 2014 03:32 am (UTC)
(Link)
О, значит %.14g.
(Reply) (Parent) (Thread)