Умножение числа с плавающей запятой дает неправильный ответ (python) - PullRequest
0 голосов
/ 04 мая 2020

мы знаем, что умножение и деление обратны друг другу, поэтому в python Предположим, у меня есть число 454546456756765675454.00 , и я хочу разделить число на 32, давайте определим переменную, например

value = 454546456756765675454.00/32

так что вывод будет, 1.4204576773648927e + 19 или 14204576773648926720.000000 , теперь я хочу умножить вывод на 32, так что если я умножу 14204576773648926720.000000 * 32 тогда на выходе я получу 454546456756765655040.00 не 454546456756765675454.00 почему это произошло? я не очень хорош в математике, но мой вопрос - почему умножение числа с плавающей запятой дает мне неправильный ответ (я также пробую десятичный модуль, но он не работает для меня, или, может быть, я не знаю, как использовать десятичный модуль для получения точного ответа)

Ответы [ 2 ]

0 голосов
/ 04 мая 2020

В широких пределах умножение и деление на степени двух, включая 32, являются точными в двоичной с плавающей запятой. Преобразование десятичной дроби неточно. 454546456756765655040 является ближайшим 64-разрядным двоичным числом IEEE 754 к 454546456756765675454. Деление и умножение на 32 не имеют значения.

В более общем случае, деление и умножение на одно и то же число могут привести к ошибке округления десятичной дроби конечной ширины / двоичный et c. дроби, если только все простые множители делителя не являются также главными факторами радиуса, используемого для представления дробей. Как в двоичной, так и в десятичной дроби деление и умножение на 3 может привести к ошибке округления, поскольку 3 является фактором, не равным ни 2, ни 10.

Деление и умножение на 32 могут быть точными, учитывая достаточное значение и ширину, в обоих случаях. десятичное и двоичное, потому что два, единственный главный фактор 32, является фактором как 10, так и 2.

0 голосов
/ 04 мая 2020

Плавающие точки хранятся в виде двоичных дробей. Некоторое число не может быть точно записано в форме базы 2. Таким образом, их приблизительное значение равно store.
Теперь, если в этом приближении была ошибка +0,0001 для некоторого числа, и если это число умножено на 10000, то наш результат сместится на значение 0,0001 * 10000 = 1.

Это практически во всех языках программирования.

Для операций, где точность очень важна, предпочтителен модуль decimal.

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

Ваш пример с использованием модуля decimal будет выглядеть примерно так:

import decimal

value = decimal.Decimal(454546456756765675454)
vd = value/decimal.Decimal(32)
vm = vd*32

diff = vm - value
assert diff == decimal.Decimal(0)
# assert diff == 0.0
...