?

Log in

No account? Create an account

Округленческое - Ваши рубидии уже у кобальта во ртути

Dec. 12th, 2014

03:58 pm - Округленческое

Previous Entry Share Next Entry

Вступление для широкого круга читателей: Вещественные числа в ЭВМ хранятся с ограниченной точностью, поэтому после выполнения операций с ними делается округление. При выполнении двух взаимоисключающих операций, требующих округления — например, деления на произвольное число, отличное от степени двойки, и умножения на него же — результат далеко не всегда оказывается равен исходному числу. Этот пост посвящен вопросу, с какой частотой результат оказывается меньше, равен и больше исходного числа.



Посчитайте, сколько раз результат деления единицы на нечетное число (например, в диапазоне от 3 до миллиона) и последующего умножения на него же оказывается меньше единицы, равен, или больше, в зависимости от типа данных, используемого для хранения промежуточных значений. Объясните полученные результаты.

Comments:

[User Picture]
From:ramlamyammambam
Date:December 13th, 2014 01:10 am (UTC)
(Link)
Да, интересно бы посмотреть.
Для всех четырех режимов округления.
(Reply) (Thread)
[User Picture]
From:spamsink
Date:December 13th, 2014 01:36 am (UTC)
(Link)
Даже с дефолтным округлением там бездна, звёзд полна. Некоторые явления я совсем не могу объяснить.
(Reply) (Parent) (Thread)
[User Picture]
From:ramlamyammambam
Date:December 13th, 2014 04:39 am (UTC)
(Link)
Получается в 14.9% случаев результат меньше единицы, и никогда больше. Это при стандартном округлении к ближайшему. Типа такого:
49: result 3fefffffffffffff
103: result 3fefffffffffffff
107: result 3fefffffffffffff
161: result 3fefffffffffffff
187: result 3fefffffffffffff
197: result 3fefffffffffffff
237: result 3fefffffffffffff
239: result 3fefffffffffffff
249: result 3fefffffffffffff
253: result 3fefffffffffffff
347: result 3fefffffffffffff
389: result 3fefffffffffffff
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:December 13th, 2014 04:47 am (UTC)
(Link)
Теперь попробуй сохранять результат деления в long double.
(Reply) (Parent) (Thread)
[User Picture]
From:ramlamyammambam
Date:December 13th, 2014 04:52 am (UTC)
(Link)
Тогда результат всегда точным получается.
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:December 13th, 2014 04:57 am (UTC)
(Link)
Прошу прощения, я имел в виду, и умножения тоже. Тогда у меня получается практически 50%/50%, с малой долей точных результатов. Это в точности то, что процессор выполняет внутри; спрашивается, почему промежуточные округления так смещают статистику вниз?
(Reply) (Parent) (Thread)
[User Picture]
From:ramlamyammambam
Date:December 13th, 2014 05:22 am (UTC)
(Link)
Да вроде нет, тоже 14.9%.
Вот исходник: https://code.google.com/p/vak-opensource/source/browse/trunk/languages/c-language/rounding.c
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:December 13th, 2014 05:45 am (UTC)
(Link)
Вместо one просто 1.0.
(Reply) (Parent) (Thread)
[User Picture]
From:ramlamyammambam
Date:December 13th, 2014 06:12 am (UTC)
(Link)
Непонятно, откуда такая разница.
(Reply) (Parent) (Thread)
[User Picture]
From:spamsink
Date:December 13th, 2014 06:29 am (UTC)
(Link)
Вот и я о том.
(Reply) (Parent) (Thread)
[User Picture]
From:ramlamyammambam
Date:December 13th, 2014 06:33 am (UTC)
(Link)
Что-то компилятор там мудрит.
(Reply) (Parent) (Thread)
[User Picture]
From:archaicos
Date:December 13th, 2014 01:43 am (UTC)
(Link)
Все это Сильно зависит от компилятора и опций. Промежуточные результаты могут храниться с большей точностью. Плюс ошибки в компиляторе. Кроме того нужно помнить про денормализованные числа вблизи нуля - у них меньше значащих разрядов, чем обычно. Там веселуха, короче.
(Reply) (Thread)
[User Picture]
From:spamsink
Date:December 13th, 2014 01:54 am (UTC)
(Link)
1. Я специально сказал, что промежуточные результаты нужно сохранять (с наперед заданной той или иной точностью, например, с помощью volatile).
2. Ошибки в компиляторе - особь статья.
3. Я специально сказал, что на что нужно делить, чтобы избежать проблем с денормализованными числами.
(Reply) (Parent) (Thread)