Каков наилучший способ сравнения чисел с плавающей точкой на почти равенство в Python? - PullRequest
270 голосов
/ 08 апреля 2011

Хорошо известно, что сравнение чисел с плавающей точкой является немного сложным из-за проблем округления и точности.

Например: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

Каков рекомендуемый способ решения этой проблемы вPython?

Конечно, есть где-то стандартная библиотечная функция для этого?

Ответы [ 14 ]

1 голос
/ 03 января 2018

Мне понравилось предложение @Sesquipedal, но с модификацией (особый вариант использования, когда оба значения равны 0, возвращает False). В моем случае я был на Python 2.7 и просто использовал простую функцию:

if f1 ==0 and f2 == 0:
    return True
else:
    return abs(f1-f2) < tol*max(abs(f1),abs(f2))
1 голос
/ 07 июля 2015

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

Подробнее см. Фракция из модуля фракций.

0 голосов
/ 09 апреля 2019

Для сравнения до заданного десятичного знака без atol/rtol:

def almost_equal(a, b, decimal=6):
    return '{0:.{1}f}'.format(a, decimal) == '{0:.{1}f}'.format(b, decimal)

print(almost_equal(0.0, 0.0001, decimal=5)) # False
print(almost_equal(0.0, 0.0001, decimal=4)) # True 
0 голосов
/ 25 ноября 2016

Это может быть немного уродливым взломом, но он работает довольно хорошо, когда вам не нужно больше, чем точность с плавающей запятой по умолчанию (около 11 десятичных знаков).Хорошо работает на python 2.7.

Функция round_to использует метод формата из встроенного класса str для округления числа с плавающей точкой дострока, которая представляет число с плавающей запятой с необходимым количеством десятичных знаков, а затем применяет встроенную функцию eval к округленной строке с плавающей запятой, чтобы вернуться к числовому типу с плавающей запятой.

The is_close функция просто применяет простое условное выражение к закругленному с плавающей точкой.

def round_to(float_num, decimal_precision):
    return eval("'{:." + str(int(decimal_precision)) + "f}'.format(" + str(float_num) + ")")

def is_close(float_a, float_b, decimal_precision):
    if round_to(float_a, decimal_precision) == round_to(float_b, decimal_precision):
        return True
    return False

a = 10.0 / 3
# Result: 3.3333333333333335
b = 10.0001 / 3
# Result: 3.3333666666666666

print is_close(a, b, decimal_precision=4)
# Result: False

print is_close(a, b, decimal_precision=3)
# Result: True
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...