Сумма двух 'np.longdouble', приводящая к числовой ошибке, не связанной с печатью - PullRequest
0 голосов
/ 12 марта 2019

Проблема, которую я пытаюсь как понять, так и решить, относится к той, которая была задана несколько лет назад в этом вопросе: Сумма двух "np.longdouble" дает большую числовую ошибку , но не связана с простой печать значений.

Предположим, что в простой библиотеке Python мы создаем два длинных типа double, как показано ниже:

a = np.longdouble('4')
b = np.longdouble('1e-3000')

Как и ожидалось, если проверять type(a) или type(b), в результате оба типа numpy.float128.

Что я хочу сделать, это просто сложить значения, хранящиеся в a и b, но просто сложив их, получим число 4:

In [3]: a + b
Out[3]: 4.0

In [4]: (a + b) == np.longdouble(4)
Out[4]: True

In [5]: (a + b) == np.longdouble('4')
Out[5]: True

In [6]: (a + b) == np.longdouble('4.0')
Out[6]: True

In [7]: (a + b) > np.longdouble('4.0')
Out[7]: False

In [8]: np.equal(a + b,np.longdouble('4.0'))
Out[8]: True

In [9]: np.greater(a + b,np.longdouble('4.0'))
Out[9]: False

In [10]: type(a + b)
Out[10]: numpy.float128

Как я полагаю, приведенные выше тесты подразумевают, что сумма между a и b свернута и фактически равна 4, независимо от того, какая сумма все еще сохраняется в объекте float128.

Обратите внимание, что то же самое не происходит с умножением или делением:

In [11]: a * b
Out[11]: 4e-300

In [12]: a / b
Out[12]: 4e+300

In [13]: b / a
Out[13]: 2.5e-301

Хотя то же самое происходит с вычитанием:

In [14]: np.equal(a - b,np.longdouble('4.0'))
Out[14]: True

In [15]: np.equal(b - a,np.longdouble('-4.0'))
Out[15]: True

In [16]: (a - b) == np.longdouble('4.0')
Out[16]: True

In [17]: (b - a) == np.longdouble('-4.0')
Out[17]: True

Следовательно, мои вопросы: почему суммирования и вычитания не работают должным образом и как я могу получить a + b в приведенных выше примерах, получим число:

4.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001

То есть в числе, чье логическое сравнение на равенство с числом 4 приводит к False.

Obs: в случае, если это имеет какое-либо значение:

In [18]: np.nextafter(np.longdouble(0),1)
Out[18]: 4e-4951

Ответы [ 2 ]

3 голосов
/ 12 марта 2019

Представьте, что вы встречаете человека, который может запомнить любое число длиной до 5 цифр и любой данный показатель степени. Таким образом, вы просите человека рассчитать следующую сумму

4.0 + 1.0E-4

Итак, этот человек достает ручку и бумагу и начинает выполнять работу:

  4.0000
  0.0001
+ ------
  4.0001

И говорит вам, что ответ 4.0001. Вы полностью сбиты с толку, так как ответ правильный. Вы хотите проверить его дальше и спросить результат:

4.0 + 1.0E-5

И человек говорит вам, что это 4. Теперь вы совершенно ошеломлены, поскольку знаете, что, если вы добавляете что-то к чему-то другому, оно должно быть больше или меньше, чем первое. Но потом вы вспоминаете, что человек может запомнить только до 5 цифр, и тогда вы замечаете:

  4.00000
  0.00001
+ -------
  4.00001

Но 4.00001 - это 6 цифр, и человек может вспомнить только 5. Так вот почему он возвращает 4.

Теперь представьте, что человек - это ваш компьютер, который может запоминать только двоичные числа со 112 цифрами и показателями между −16382 и 16383, а также знак числа.

1 голос
/ 12 марта 2019

10^3 - это приблизительно 2^10, так что вы понимаете, что 1e-3000 - это примерно 2^-10,000?

Итак, вы добавляете это крошечное количество к 4 (2 ^ 2) и не хотитеразница в исчезновении, понимаете ли вы, что для значащих значений требуется более десяти тысяч бит?

Как вы думаете, может ли 128-битная плавающая точка содержать столько бит?

Фактэто крошечное число представимо, связано с тем, что абсолютная точность с плавающей точкой является плавающей ... потому что плавающая точка представлена ​​внутри с масштабированием (-1)^sign_bit * 2^exponent * significand.Но это не означает, что относительная точность настолько высока!

Число битов, используемых для представления показателя степени и значения, фиксировано для double, longdouble и т. Д. *

Количество битЗарезервировано для показателя степени. Зафиксируйте диапазон представимых значений.
Количество битов, используемых для значения и установите относительную точность.

Это очень базовые понятия с плавающей запятой, и вам обязательно следует прочитатьссылки на странице информации https://stackoverflow.com/tags/floating-point/info

...