2013-05-02 4 views
1

Я только начинаю с python (python3), потому что я читаю его полезность для проекта эйлера, так как он может обрабатывать очень большие числа.python long number data loss

сейчас я борюсь с довольно простой проблемой преобразования float в int. Почему я не получаю тот же результат для этого:

num = 6008514751432349174082765599289028910605977570 

print('num  {0} '.format(int(num))) 

num = num/2 
print('num /2 {0} '.format(int(num))) 

num = num * 2 
print('num *2 {0} '.format(int(num))) 

выход для этого:

num  6008514751432349174082765599289028910605977570 
num /2 3004257375716174771611310192874715313222975488 
num *2 6008514751432349543222620385749430626445950976 

ответ

6

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

Не делайте этого, что приводит к потере данных. Используйте integer (floor) division with // вместо:

>>> 6008514751432349174082765599289028910605977570 // 2 * 2 
6008514751432349174082765599289028910605977570 

Это все еще может привести к ошибкам округления, конечно, если входное значение не делится на 2 без настила:

>>> 6008514751432349174082765599289028910605977571 // 2 * 2 
6008514751432349174082765599289028910605977570 

но значения с плавающей запятой ограничены в точности на основе ваша точная поддержка процессора; см. sys.float_info, чтобы узнать, какие точные ограничения, которые ваша платформа налагает на числа с плавающей точкой.

На моем Mac sys.float_info.dig говорит, что моя платформа поддерживает 15 цифр точности, но вы делите 46-значное целое число. Это означает, что вы выбрасываете нижнюю цифры от вашего большого целого числа с плавающей точкой при использовании разделения:

>>> len(str(int(6008514751432349174082765599289028910605977570/2) - (6008514751432349174082765599289028910605977570 // 2))) 
30 

Это является много потери точности там. :-)

+0

ах, идеальный. спасибо – santa

+0

@MartijnPieters, когда кто-то использует '//' вместо '/'? – dustin

+1

@ dustin: если вы хотите применить целочисленное деление (поэтому результатом является 'int') вместо значения с плавающей запятой. –