2015-05-21 4 views
1

У меня возникли проблемы с пониманием некоторых результатов, которые я получаю при работе с Python 2.7.Точка с плавающей точкой в ​​Python 2.7

>>> x=1 
>>> e=1e-20 
>>> x+e 
1.0 
>>> x+e-x 
0.0 
>>> e+x-x 
0.0 
>>> x-x+e 
1e-20 

Это копируется непосредственно из Python. У меня есть класс о том, как программировать на Python, и я не понимаю несоответствия результатов (x + e == 1, x-x + e == 1e-20, но x + ex == 0 и e + xx = = 0).

Я уже прочитал учебник Python на ошибки репрезентации, но я считаю, что ни один из не был упомянут там

Заранее спасибо

ответ

4

с плавающей точкой дополнение не ассоциативно.

x+e-x сгруппирован как (x+e)-x. Он добавляет x и e, округляют результат до ближайшего представляемого числа (которое 1), а затем вычитает x из результата и раундов снова, производя 0.

x-x+e группируются в (x-x)+e. Он вычитает x из x, производя 0 и округляя его до ближайшего представимого числа, которое равно 0. Затем он добавляет e в 0, производя e и округляя его до ближайшего представимого числа, которое равно e.

+0

@chepner: Нет, это коммутативно. Нам также потребуется ассоциативность для выполнения преобразований '(x + e) ​​-x'->' x + (ex) '->' x + (- x + e) ​​'->' (x + -x) + e'-> '(хх) + é'. – user2357112

+0

Итак: в случае e + x-x добавление будет (e + x) = 1 (ближайшее представимое число), за которым следует 1-1 = 0 (ближайшее представимое число). Правильно? –

+0

@ Хосе: Правильно. – user2357112

2

Это связано с тем, как компьютеры представляют floating point numbers.

Это все действительно в двоичном формате, но давайте притворимся, что оно работает с номерами оснований 10, потому что нам гораздо легче относиться к ним.

Число с плавающей запятой выражается в форме 0.x*10^y где x - это 10-значное число (здесь я опускаю конечные нули), а y - показатель степени. Это означает, что число 1.0 выражается как 0.1*10^1, а число 0,1 - 0.1*10^0.

Чтобы добавить эти два номера вместе, мы должны убедиться, что они имеют одинаковый показатель степени. Мы можем сделать это легко, сдвинув числа назад и вперед, то есть мы изменим 0.1*10^0 на 0.01*10^1, а затем добавим вместе, чтобы получить 0.11*10^1.

Когда мы 0.1*10^1 и 0.1*10^-19 (1e-20) мы сместится 0.1*10^-19 20 шагов, а это означает, что 1 будет выходить за пределы диапазона нашего 10 числа цифр, поэтому мы в конечном итоге с 0.1*10^1 + 0.0*10^1 = 0.1*10^1.

Причина вы в конечном итоге с 1e-20 в последнем примере, потому что сложение производится слева направо, поэтому мы вычитаем 0.1*10^1 от 0.1*10^1 заканчивая 0.0*10^0 и добавить 0.1*10^-19 к тому, который представляет собой особый случай, когда мы не нужно менять ни одну из них, потому что одна из них ровно равна нулю.

Смежные вопросы