Деление с плавающей точкой против целочисленного деления дает другой ответ

1

У меня были некоторые проблемы с куском кода и в итоге я сделал следующий фрагмент командной строки. Это был просто эксперимент, и я не хранил такие большие значения в любой переменной в реальном коде (по модулю 10 ** 9 +7).,

>>> a=1
>>> for i in range(1,101):
...     a=a*i
...
>>> b=1
>>> for i in range(1,51):
...     b=b*i
...
>>> c=pow(2,50)
>>> a//(b*c)
2725392139750729502980713245400918633290796330545803413734328823443106201171875
>>> a/(b*c)
2.7253921397507295e+78
>>> (a//(b*c))%(10**9 +7)
196932377
>>> (a/(b*c))%(10**9 +7)
45708938.0
>>>

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

В основном я вычислил: ( (100!)/((50!)*(2^50)) ) % (10**9 +7)

  • 0
    Поскольку целые числа могут быть любого размера (то есть иметь любое количество значащих цифр) в Python (с учетом ограничений памяти), это, однако, неверно для значений с плавающей запятой (что, как я полагаю, вы подразумеваете под "десятичным").
  • 1
    Есть модуль с именем mpmath который поддерживает выполнение арифметики с плавающей точкой произвольной точности.
Показать ещё 4 комментария
Теги:
python-3.x

2 ответа

3
Лучший ответ

Из-за точности.

Целые числа и поплавки кодируются по-разному. В частности, в python 3 целые числа могут быть сколь угодно большими - то, которое вы дали, например, больше 250 бит, когда вы конвертируете его в двоичный. Они хранятся таким образом, который может приспосабливаться, насколько они велики.

Однако числа с плавающей запятой ограничены определенным размером - обычно 64 бит. Эти 64 бита делятся на знак (1 бит), мантисса и экспонента - количество бит в мантиссе ограничено, насколько точным может быть число. Документация Python содержит раздел об этом ограничении.

Итак, когда вы это делаете

(a//(b*c))%(10**9 +7)

вы выполняете этот расчет с целыми числами, которые, опять же, сколь угодно велики. Однако, когда вы это делаете:

(a/(b*c))%(10**9 +7)

вы выполняете этот расчет с числом, которое имеет только 18 значащих цифр - оно уже неточно, и выполнение большего количества вычислений с ним только еще больше развращает ответ.

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

2

Причина в том, что целые числа точны, но поплавки ограничены точностью с плавающей запятой: точность поплавка по умолчанию Python2.7

  • 0
    Что происходит, когда десятичное число пересекает 53-значный предел (в точности с плавающей запятой)? как остальные цифры заполнены значениями мусора?
  • 2
    Когда десятичная дробь становится слишком большой для удержания числа с плавающей запятой, она теряет точность - остальные цифры просто исчезают . Это в основном округление, но в двоичном формате. Например, число 5529771903 округленное до пяти значащих цифр, будет 5529700000 .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню