Мне пришло в голову, что хорошим способом сравнения поплавков является масштабирование допуска с помощью поплавков. Это хорошая идея?Использование масштабированной толерантности для сравнения поплавков
Эта рутина должна быть расширена для специальных величин, таких как NaN, +/- Inf, но это дает основную идею.
def FloatEq(a, b, ToleranceFactor=1e-6):
if a == b: return True
c = min(abs(a), abs(b))
return(abs(a-b) < (c*ToleranceFactor))
a = 0.000000000001
b = 0.000000000001000000001
print('Straight compare ==', a==b)
print('FloatEq(,,1e-6) ==', FloatEq(a,b))
print('FloatEq(,,1e-10) ==', FloatEq(a,b,1e-10))
Выход:
Straight compare == False
FloatEq(,,1e-6) == True
FloatEq(,,1e-10) == False
ОБНОВЛЕНИЕ:
Одно из возможных решений, который может обрабатывать один из операндов, равным нулю. Он использует фиксированный, настраиваемый пользователем допуск, а не фактор.
def FloatEq(a, b, ToleranceFactor=1e-6, ToleranceAtZero=None):
if a == b:
return True
elif a==0 or b==0:
c = a if b==0 else b
if ToleranceAtZero is None:
import sys
# Ignoring denormalized numbers for now
ToleranceAtZero = sys.float_info.min
return abs(c) < ToleranceAtZero
else:
c = min(abs(a), abs(b))
return(abs(a-b) < (c*ToleranceFactor))
Это зависит от вашего прецедента, но я видел худшие попытки сравнить значения с плавающей запятой. Просто обратите внимание, что ваша логика несколько запутана. Вы можете избавиться от всех вещей 'if' /' else', если примените 'abs' к разнице и используйте' min (abs (a), abs (b)) '. Также обратите внимание, что ваш последний «возврат» является фиктивным. Также подумайте о том, что одно значение равно нулю. Какой терпимость вы хотите использовать в этом случае? – 5gon12eder
Я очистил его. Я хочу применить коэффициент допуска к float с меньшим абсолютным значением. Если одно значение равно нулю, результатом будет 'False', что здесь кажется уместным. – mcu
Почему бы не просто: isEqual = lambda (t, a, b): abs (a) - abs (b)
labheshr