Грешки при закръгляване с плаващи числа в Python с помощта на Numpy

Имам проблем, който вярвам, че е свързан с работата с плувки и прецизност, но не съм много добре запознат с различните тънкости. Аз съм математик и според мен все още може да работя с десетични знаци върху черна дъска. Ще започна да изучавам това, но междувременно се чудя дали има някакви общи техники за работа с плувки, които биха могли да решат проблема, който ще очертая по-долу.

Имам numpy масив от десетични знаци, които бих искал да закръгля до най-близкия .02. Първоначално постигнах това, като разделих всеки елемент от масива на .02, закръглих резултата и след това умножих отново по .02. Действителните данни се генерират от някакъв код, който обработва вход, но това демонстрира проблема:

x = np.array([.45632, .69722, .40692])
xx = np.round(x/.02)*.02

Изглежда закръгля всичко правилно, както мога да проверя:

xx
array([0.46, 0.7, 0.4])

Въпреки това, ако проверя първия и втория елемент, получавам:

xx[0]
0.46000000000000002
xx[1]
0.70000000000000007

Всеки елемент в масива е от тип numpy.float64. Проблемът възниква по-късно, защото включвам тези числа с оператори за сравнение, за да избера подмножества от данните и какво се случва след това е малко непредвидимо:

xx[0] == .46
True

Но,

xx[1] == .70
False

Както казах, имам работа за това конкретно приложение, но се чудя дали някой има начин да накара първия ми подход да работи или има техники за работа с тези типове числа, които са по-общи, отколкото трябва да бъда наясно с.


person user3749714    schedule 26.08.2014    source източник
comment
Вероятно трябва да сравнявате плаващи числа без оператора ==. Вместо това сравнете числото с диапазон от стойности, като xx[0] е в рамките на 1e-10 от 0,46?. Или просто не използвайте плаващи числа (запазете всяко число като 100 пъти повече от това, което е в действителност).   -  person irrelephant    schedule 26.08.2014
comment
трябва да погледнете isclose или allclose в (numpy)[docs.scipy.org/doc/numpy-dev/reference/generated/.   -  person Marcin    schedule 26.08.2014
comment
Задължителна връзка: floating-point-gui.de   -  person Warren Weckesser    schedule 26.08.2014


Отговори (2)


Вместо да използвате == за избор на подгрупи от данни, опитайте да използвате numpy .isclose(). Това ви позволява да посочите относителна/абсолютна толерантност за вашето сравнение (absolute(a - b) <= (atol + rtol * absolute(b)))

person Joel Vroom    schedule 26.08.2014
comment
Всъщност щях да отговоря на собствения си въпрос и да предложа приемлива разлика и оператора ‹, но това е малка полезна функция, която трябва да знаете. - person user3749714; 27.08.2014
comment
връзката е повредена (не може да се редактира): docs.scipy. org/doc/numpy/reference/generated/numpy.isclose.html - person K.S.; 04.01.2020

format на Python също може да се използва за това.

print format(xx[1], '.100f')

този код връща действителната стойност на xx[1]

ie. xx[1] = 0.70000000000000006661338147750939242541790008544921875

Можете да ги проверите чрез кода, показан по-долу

if xx[1] == 0.70000000000000006661338147750939242541790008544921875:
    print 'true'
person Aslam Khan    schedule 26.08.2014