Равенство двойных граничных значений - PullRequest
1 голос
/ 01 мая 2019

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

Я попытался выделить проблемы и обнаружил, что равенство больших двойных значений вызывает мои проблемы.Я попытался изменить максимальное значение, чтобы оно не было тесно привязано к максимальному значению, однако безуспешно

// Evaluates to true.
var Equal11 = Double.MaxValue - 100d == Double.MaxValue - 200d;
var Equal12 = (Double.MaxValue - 100d).Equals(Double.MaxValue - 200d);

// Evaluates to false.
var Equal21 = 100d == 200d;
var Equal22 = (100d).Equals(200d);

Я ожидал бы, что Equal11 и Equal12 будут ложными, так как Equal21 и Equal22 не равны.

Я предполагаю, что double как-то округляет свое значение близко к Double.MaxValue, однако я не понимаю, как с этим работать.

1 Ответ

3 голосов
/ 02 мая 2019

Предполагается, что Double представлен 64-битной двоичной плавающей точкой IEEE 754:

Разрыв между последовательными числами с плавающей точкой увеличивается с увеличением числа. Во всем нормальном конечном диапазоне имеются значения 2 52 в диапазоне [2 n , 2 n + 1 ).

Double.MaxValue составляет около 1,7796931348623157e308. Наибольшее представимое значение строго меньше, чем около 1.7976931348623155e308, разница 1.9958403095347198e292. Результат вычитания googol из Double.MaxValue раундов до Double.MaxValue, объясняющий отсутствие какой-либо разницы между вычитанием 100 и вычитанием 200.

Все целые числа в диапазоне [- (2 53 ), 2 53 ] точно представимы. Любая пара различных целых чисел в этом диапазоне будет сравниваться неравно, объясняя, что 100 не равно 200.

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

...