Неожиданное поведение Math.Floor(double) и Math.Ceiling(double)

Этот вопрос касается порога, при котором 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)?

10
задан sarnold 28 March 2012 в 22:52
поделиться