Этот вопрос касается порога, при котором Math.Floor(double)
и Math.Ceiling(double)
решают чтобы дать вам предыдущее или следующее целочисленное значение. Я был обеспокоен, обнаружив, что порог, похоже, не имеет ничего общего с Double.Epsilon
, который является наименьшим значением, которое может быть представлено двойным значением. Например:
double x = 3.0;
Console.WriteLine( Math.Floor( x - Double.Epsilon ) ); // expected 2, got 3
Console.WriteLine( Math.Ceiling( x + Double.Epsilon) ); // expected 4, got 3
Даже умножение Double.Epsilon
на изрядное количество не помогло:
Console.WriteLine( Math.Floor( x - Double.Epsilon*1000 ) ); // expected 2, got 3
Console.WriteLine( Math.Ceiling( x + Double.Epsilon*1000) ); // expected 4, got 3
После некоторых экспериментов я смог определить, что порог находится где-то в районе 2,2E-16. , что очень мало, но ЗНАЧИТЕЛЬНО больше, чем Double.Epsilon
.
Причина, по которой возник этот вопрос, заключается в том, что я пытался вычислить количество цифр в числе по формуле var digits = Math.Floor( Math.Log( n, 10 )) + 1
. Эта формула не работает для n=1000
(на которое я наткнулся совершенно случайно), потому что Math.Log( 1000, 10 )
возвращает число, которое на 4,44E-16 меньше его значения. реальная стоимость.(Позже я обнаружил, что встроенный Math.Log10(double)
дает гораздо более точные результаты.)
Не следует ли привязывать порог к Double.Epsilon
или , если нет, то не должен ли порог быть задокументирован (я не нашел упоминания об этом в официальной документации MSDN)?