Почему `n% int (m)! = N% float (m)`? - PullRequest
       0

Почему `n% int (m)! = N% float (m)`?

0 голосов
/ 16 января 2020

Почему модуль отличается для одного и того же числа с одним и тем же делителем, который представлен как float и int? Или например почему 10**23 % int(9)! = 10**23 % float(9)?

for i in range(1, 30):
   print(i, 10**i % 9, 10**i % 9.0)

Выходы:

1 1 1.0
2 1 1.0
3 1 1.0
4 1 1.0
5 1 1.0
6 1 1.0
7 1 1.0
8 1 1.0
9 1 1.0
10 1 1.0
11 1 1.0
12 1 1.0
13 1 1.0
14 1 1.0
15 1 1.0
16 1 1.0
17 1 1.0
18 1 1.0
19 1 1.0
20 1 1.0
21 1 1.0
22 1 1.0
23 1 5.0    <--- Why?  10**23 % 9 != 10**23 % 9.0
24 1 0.0    And so on in no particular order.
25 1 1.0
26 1 6.0
27 1 1.0
28 1 2.0
29 1 1.0

Python 3.8.1

Ответы [ 3 ]

4 голосов
/ 16 января 2020

Для выполнения 10**23%9.0 значение 10**23 преобразуется в число с плавающей точкой. Поплавки являются приблизительными. Значение, которое вы фактически получаете, если вы представляете 10**23 как число с плавающей точкой, довольно далеко от точного значения.

>>> x = float(10**23)
>>> int(x)
99999999999999991611392
0 голосов
/ 16 января 2020

Точность с плавающей точкой. Когда вы делаете модуль с плавающей точкой, значение преобразуется в число с плавающей точкой, и 10 ^ 23 оказывается больше, чем числа, которые могут быть представлены естественным образом. Мы можем точно видеть, что происходит, используя Decimal:

>>> from decimal import Decimal
>>> (sign, mantissa, exponent) = Decimal(10**23).as_tuple()
>>> sign, mantissa, exponent
(0, (1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), 0)
>>> (sign, mantissa, exponent) = Decimal(float(10**23)).as_tuple()
>>> sign, mantissa, exponent
(0, (9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 1, 6, 1, 1, 3, 9, 2), 0)
0 голосов
/ 16 января 2020

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

Мы можем показать это, преобразовав большое значение int 10**i в float и обратно, и сравнив его с исходным значением int:

>>> for i in range(1, 30):
...    print(i, 10**i, int(float(10**i)) - 10**i)
... 
1 10 0
2 100 0
3 1000 0
4 10000 0
5 100000 0
6 1000000 0
7 10000000 0
8 100000000 0
9 1000000000 0
10 10000000000 0
11 100000000000 0
12 1000000000000 0
13 10000000000000 0
14 100000000000000 0
15 1000000000000000 0
16 10000000000000000 0
17 100000000000000000 0
18 1000000000000000000 0
19 10000000000000000000 0
20 100000000000000000000 0
21 1000000000000000000000 0
22 10000000000000000000000 0
23 100000000000000000000000 -8388608
24 1000000000000000000000000 -16777216
25 10000000000000000000000000 905969664
26 100000000000000000000000000 4764729344
27 1000000000000000000000000000 13287555072
28 10000000000000000000000000000 -416880263168
29 100000000000000000000000000000 -8566849142784
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...