В csh почему 4 - 3 + 1 == 0?

Modulo дает вам rest деления. 3.5, деленная на 0.1, должна дать вам 35 с остальной частью 0. Но поскольку поплавки основаны на степенях двух, цифры не являются точными , и вы получаете ошибки округления.

Если вам нужно, чтобы ваше деление десятичных чисел было точным, используйте десятичный модуль:

>>> from decimal import Decimal
>>> Decimal('3.5') / Decimal('0.1')
Decimal('35')
>>> Decimal('3.5') % Decimal('0.1')
Decimal('0.0')

Поскольку меня избивают, что мой ответ вводит в заблуждение, здесь идет вся история:

0.1 немного больше 0.1

>>> '%.50f' % 0.1
'0.10000000000000000555111512312578270211815834045410'

Если вы разделите поплавок 3.5 на такое число, вы получите остаток почти 0.1.

Давайте начнем с номера 0.11 и продолжим добавлять нули между двумя 1, чтобы уменьшить его, сохраняя его больше, чем 0.1.

>>> '%.10f' % (3.5 % 0.101)
'0.0660000000'
>>> '%.10f' % (3.5 % 0.1001)
'0.0966000000'
>>> '%.10f' % (3.5 % 0.10001)
'0.0996600000'
>>> '%.10f' % (3.5 % 0.100001)
'0.0999660000'
>>> '%.10f' % (3.5 % 0.1000001)
'0.0999966000'
>>> '%.10f' % (3.5 % 0.10000001)
'0.0999996600'
>>> '%.10f' % (3.5 % 0.100000001)
'0.0999999660'
>>> '%.10f' % (3.5 % 0.1000000001)
'0.0999999966'
>>> '%.10f' % (3.5 % 0.10000000001)
'0.0999999997'
>>> '%.10f' % (3.5 % 0.100000000001)
'0.1000000000'

В последней строке создается впечатление, что мы наконец достигли 0.1, но изменение строк формата показывает true nature:

>>> '%.20f' % (3.5 % 0.100000000001)
'0.09999999996600009156'

Формат поплавка по умолчанию для python по умолчанию просто не показывает достаточную точность, чтобы 3.5 % 0.1 = 0.1 и 3.5 % 0.1 = 35.0. Это действительно 3.5 % 0.100000... = 0.999999... и 3.5 / 0.100000... = 34.999999..... В случае разделения вы даже получаете результат точный , поскольку 34.9999... с округлением до 35.0.


Удовлетворительный факт: если вы используете число, которое немного меньше, чем 0.1, и выполните ту же операцию, в которой вы получите число, которое немного больше 0:

>>> 1.0 - 0.9
0.09999999999999998
>>> 35.0 % (1.0 - 0.9)
7.771561172376096e-15
>>> '%.20f' % (35.0 % (1.0 - 0.9))
'0.00000000000000777156'

Используя C ++, вы можете даже показать, что 3.5, деленный на поплавок 0.1, не 35, но немного меньше.

#include 
#include 

int main(int argc, char *argv[]) {
    // double/float, rounding errors do not cancel out
    std::cout << "double/float: " << std::setprecision(20) << 3.5 / 0.1f << std::endl;
    // double/double, rounding errors cancel out
    std::cout << "double/double: " << std::setprecision(20) << 3.5 / 0.1 << std::endl;
    return 0;
}

http://ideone.com/fTNVho

В Python 3.5 / 0.1 вы получите точный результат 35, потому что ошибки округления компенсируют друг друга. Это действительно 3.5 / 0.100000... = 34.9999999.... И 34.9999... предельно длинный, так что вы в конечном итоге с точностью до 35. Программа C ++ показывает это хорошо, поскольку вы можете смешивать double и float и играть с точностью до чисел с плавающей запятой.

13
задан Rob Wells 18 June 2009 в 00:04
поделиться

3 ответа

Хотя вы ожидаете, что операторы будут левоассоциативными, они правоассоциативны в csh , поэтому он оценивается как 4- (3 + 1)

   -
  / \
 /   \
4     +
     / \
    3   1
33
ответ дан 1 December 2019 в 17:26
поделиться

Операторы + и - правоассоциативны в csh. Это означает, что «4 - 3 + 1» оценивается как «4 - (3 + 1)».

21
ответ дан 1 December 2019 в 17:26
поделиться

Группировка операторов. Он читает операцию как 4 - (3 + 1), а не (4 - 3) +1.

3
ответ дан 1 December 2019 в 17:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: