Нежелательное округление при вычитании массивов numpy в Python

Я столкнулся с проблемой, когда python автоматически округляет очень маленькие числа (меньше 1е-8) при вычитании массива из одного поплавка. Возьмем следующий пример:

import numpy as np float(1) - np.array([1e-10, 1e-5]) 

Любые мысли о том, как заставить питона не округлить? Это заставляет меня делить на ноль в некоторых случаях и становиться проблемой. Та же проблема возникает при вычитании из массива numpy.

    В основном, это просто repr массивов numpy, которые вас обманывают.

    Рассмотрим приведенный выше пример:

     import numpy as np x = float(1) - np.array([1e-10, 1e-5]) print x print x[0] print x[0] == 1.0 

    Это дает:

     [ 1. 0.99999 ] 0.99999999999 False 

    Таким образом, первый элемент на самом деле не равен нулю, это просто красивая печать массивов numpy, которые показывают это именно так.

    Это можно контролировать с помощью numpy.set_printoptions .

    Конечно, numpy финансируется с использованием ограниченных прецизионных поплавков. Вся точка numpy должна быть эффективным для памяти контейнером для массивов подобных данных, поэтому нет эквивалента decimal класса в numpy.

    Однако 64-битные поплавки имеют достойный диапазон точности. Вы не столкнетесь с множеством проблем с 1e-10 и 1e-5. Если вам нужно, есть также numpy.float128 dtype, но операции будут намного медленнее, чем использование собственных поплавков.

    Я предполагаю, что все это зависит от обработки очень маленьких чисел с плавающей точкой, от Python и от базовых библиотек C, которые в определенный момент имеют тенденцию к снижению точности.

    Если вам нужен такой уровень точности, imho вы должны полагаться на что-то другое, например, на дробные числа и т. Д.

    Я не знаю, есть ли что-то для этого, но если бы вы могли представить эти числа по-другому (например, 1/10000000000 и 1/100000 ), а затем вычислить результат с плавающей запятой только в конце все расчеты, вы должны избегать всех этих проблем.

    (Конечно, вам нужен какой-то класс, который автоматически обрабатывает фракционные вычисления, чтобы избежать необходимости переопределять формулы и т. Д.)