Округление странности – что особенного в «100»?

У кого-нибудь есть объяснение этого странного округления в haskell (GHCi, версия 7.2.1). Все кажется прекрасным, если я не умножусь на 100.

*Main> 1.1 1.1 *Main> 1.1 *10 11.0 *Main> 1.1 *100 110.00000000000001 *Main> 1.1 *1000 1100.0 *Main> 1.1 *10000 11000.0 

Изменить: меня толкает, что ошибка округления отображается только при умножении на 100.

Редактировать (2): полученные мной комментарии заставили меня понять, что это полностью не связано с haskell, но общая проблема с числами с плавающей запятой. Многочисленные вопросы уже задавались (и отвечали) о странностях чисел с плавающей запятой, где проблема с неопределенностью типично вводила в заблуждение поплавки с действительными числами.

Perl, python, javascript и C весь отчет 1.1 * 100.0 = 110.00000000000001 . Вот что делает C

 double 10.0 * 1.1 = 11.000000000000000000000000 double 100.0 * 1.1 = 110.000000000000014210854715 double 110.0 = 110.000000000000000000000000 double 1000.0 * 1.1 = 1100.000000000000000000000000 

Вопрос «почему это происходит только при умножении на 100» (хотя есть точное представление для 110.0) по-прежнему остается без ответа, но я полагаю, что нет простого ответа, кроме как полностью переходить на умножение с плавающей запятой (спасибо Дакс Фоль подчеркивает, что 10 ничего особенного в двоичном коде)

Вопрос «почему это происходит только при умножении на 100» (хотя есть точное представление для 110.0) по-прежнему остается без ответа, но я полагаю, что нет простого ответа, кроме как полностью переходить на умножение с плавающей запятой

Ну, я думаю, что могут быть вещи, которые можно сказать, не дожидаясь длины записи двоичного умножения, предполагая арифметику IEEE 754 и режим округления до ближайшего округления (по умолчанию).

Двойной 1.1d является половиной ULP от действительного числа 1.1. Когда вы умножаете его на 10, 100, 1000 и еще несколько степеней в десять, вы умножаетесь на число N, которое точно представляется как двойное, с дополнительным свойством, что результат действительного умножения 1.1 * N точно представляется как двойной, тоже. Это делает 1.1 * N хорошим кандидатом для результата умножения с плавающей запятой, который мы будем писать RN (N * 1.1d). Но все же умножение не будет автоматически округлено до 1.1 * N:

 RN(N * 1.1d) = N * 1.1d + E1 with |E1| <= 0.5 * ULP(N*1.1d) = N * (1.1 + E2) + E1 with |E2| <= 0.5 * ULP(1.1) = N * 1.1 + (N * E2 + E1) 

И теперь вопрос в том, как | N * E2 + E1 | сравнивается с ULP (N * 1.1d), так как мы предположили, что N * 1.1 является точно числом с плавающей запятой, если результат умножения (который также является числом с плавающей запятой) находится в пределах 1 ULP от N * 1.1 , он должен быть N * 1.1.


Короче говоря, это не так много, что особенное в 100 ... Это то, что особенно важно в реальном 1.1d * 100, которое 1) близко к силе двух, находясь под ним, и 2) имеет ошибку того же знака, что и ошибка при преобразовании реального 1.1 в двойную.

Всякий раз, когда реальный N * 1.1d относительно близок к ближайшей низшей силе в два, чем 1,1, равен 1, результат умножения с плавающей запятой 1.1d на N должен быть точно N * 1.1 (я думаю). Примером этого случая является N = 1000, N * 1.1d ~ 1100, чуть выше 1024.

Когда реальный N * 1.1d относительно близок к сразу превосходящей мощности в два, чем 1,1, равен 2, может быть число с плавающей запятой, которое представляет N * 1.1d лучше, чем N * 1.1. Но если ошибки E1 и E2 компенсируют друг друга (т. Е. Имеют противоположные знаки), это не должно происходить.

Число 1.1 не может быть представлено в конечном виде в двоичном виде. Он выглядит как 1.00011001100110011 …

«Ошибки округления» математически неизбежны с помощью простой арифметики с плавающей запятой . Если вы хотите точности, используйте тип десятичного числа.

http://support.microsoft.com/kb/42980

Interesting Posts

какова хорошая постоянная структура коллекций для использования в java?

Как реализовать Yii2 Modal Dialog на кнопке просмотра и обновления Gridview?

32-битный максимальный размер окна с дискретной графической картой

Как получить первичный ключ таблицы?

Укажите пользовательский формат даты для аргумента colClasses в read.table / read.csv

Обработка ошибок в математических функциях

Есть ли API-интерфейс для рефакторинга Eclipse, который я могу назвать программным?

Раздражает всплывающее окно OneDrive в Windows 10

Два пересечения прямоугольников

AutoHotkey (клавиатура ЕС): как переназначить LCtrl при сохранении AltGr

Java Generics: List, List , List

Почему мой компьютер загружается медленным при подключении USB-накопителя?

Ссылки Fancybox не отображаются в лайтбокс – что мне не хватает?

Наличие персональной учетной записи Skydrive в школьной школе с Windows 8

Доступ к файлам из сетевого ресурса в веб-приложении c #

Давайте будем гением компьютера.