2015-10-25 2 views
1

Мне пришло в голову, что хорошим способом сравнения поплавков является масштабирование допуска с помощью поплавков. Это хорошая идея?Использование масштабированной толерантности для сравнения поплавков

Эта рутина должна быть расширена для специальных величин, таких как 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)) 
+1

Это зависит от вашего прецедента, но я видел худшие попытки сравнить значения с плавающей запятой. Просто обратите внимание, что ваша логика несколько запутана. Вы можете избавиться от всех вещей 'if' /' else', если примените 'abs' к разнице и используйте' min (abs (a), abs (b)) '. Также обратите внимание, что ваш последний «возврат» является фиктивным. Также подумайте о том, что одно значение равно нулю. Какой терпимость вы хотите использовать в этом случае? – 5gon12eder

+0

Я очистил его. Я хочу применить коэффициент допуска к float с меньшим абсолютным значением. Если одно значение равно нулю, результатом будет 'False', что здесь кажется уместным. – mcu

+0

Почему бы не просто: isEqual = lambda (t, a, b): abs (a) - abs (b) labheshr

ответ

0

Это разумная идея, если вы не сравнивая значения, которые могли бы быть результатом catastrophic cancellation (например, вычитание два соседних чисел для получения очень небольшой, очень неточный, номера). В этом случае, я думаю, вы должны масштабировать свой допуск по величине значений предварительной отмены.

Я не численный расчет/эксперт с плавающей запятой. Правильное использование этого материала жестко, и для него есть целый стек: Computational Science.SE. Вероятно, это хороший вопрос для этого сайта. Вы даже можете попросить модератора переместить этот существующий вопрос. (отметьте это.)

Некоторые поисковые запросы: https://scicomp.stackexchange.com/questions/3362/relative-comparison-of-floating-point-numbers с несколькими ответами о сравнении FP.

Смежные вопросы