2013-09-10 1 views
1

Надеюсь, кто-то может помочь мне с объяснением этого странного результата на большом делителе или предложить мне несколько ключевых слов, чтобы я мог лучше искать.Ошибка с Python modulo на научной нотации

>>> m = 1e9+9 
>>> n = 1000000009 
>>> m == n 
True 
>>> 2549015908609065 % m 
885667930.0 
>>> 2549015908609065 % n 
885667930 
>>> 2549015908609065L % n 
885667930L 
>>> 2549015908609065L % m 
885667930.0 

>>> 254901590860906524041412370460835L % m 
98506080.0 
>>> 254901590860906524041412370460835L % n 
327998297L 

>>> 254901590860906524041412370460835L % int(m) 
327998297L 
+2

плавающей точкой на больших чисел уменьшается. См. 'Sys.float_info()' для получения точной точности. –

ответ

1

m = 1e9+9 хранит число как поплавок; однако n = 1000000009 сохраняет числа как целое число.

Когда вы делите целочисленное число на float, python неявно выводит поплавок в результате; Однако, когда вы делите целое число на другое целое число, вы получаете интегральный коэффициент. Точность Float над большими номерами уменьшается.

Если вы заметили,

>>> 254901590860906524041412370460835L % m 
98506080.0 
#outputted a float with different precision 

>>> 254901590860906524041412370460835L % n 
327998297L 
#outputted a long int 

http://www.tutorialspoint.com/python/python_numbers.htm Проверка для базового учебника по номерам питона

+0

«То, как номера интерпретируются в питоне», может привести к неправильным выводам. Таким образом, поплавки (IEEE 754) интерпретируются каждым языком программирования. – Matthias

+0

@Matthias Да, этот бит вводит в заблуждение, отредактировал его. –

+0

Спасибо всем за то, что указали на точность чисел с плавающей точкой. Я предполагал, что 2549015908609065L достаточно велико, чтобы увидеть ошибку, если она есть. Хороший урок узнал об этой ошибке. Еще раз спасибо! – bizi

2

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

Для выполнения точных операций на очень большом количестве, вы можете использовать десятичный класс следующим образом:

from decimal import * 
print Decimal(2549015908609065) % Decimal(1e9) # Gives the answer you expect 
+0

Чрезвычайно необычно требовать ничего, кроме целых, для модульной арифметики. (Действительный математик, вероятно, посмотрел бы на вас смешно, если бы вы сказали, что хотите использовать мод на чем-нибудь еще.) Таким образом, вы можете просто использовать 'int', а не' Decimal'. –

+0

@JohnY Реальному математику может это не понравиться, но операция по модулю чисел с плавающей запятой имеет точную дефиницию «Вычисляет оставшуюся часть операции деления x/y, то есть значение x-ny для некоторого целого n, величина результата меньше величины y. " и не так уж и необычно использовать его. Например: если точка перемещается по кругу и расстояние, которое оно переместило, по модулю 2 * pi даст вам местоположение точки на круге. – Dhara

+1

. Частный случай радиальной арифметики всегда совпадает с ** ** ** * pi (а не произвольные действительные числа). Ни 'float', ни' Decimal' не могут точно представлять pi, поэтому попытка вычислить его таким образом будет неточной. Если вы выполняете инженерную задачу, которая не требует точной математики, тогда 'float' будет уже достаточно хорош. Поэтому 'Decimal' не покупает вам ничего в любом случае. Если вы делаете теорию чисел, вам нужно 'int'; если вы занимаетесь разработкой, 'float' будет достаточно точным; и как 'int', так и' float' быстрее, чем 'Decimal'. –