Я пытаюсь округлить число до первого десятичного знака и, учитывая различные варианты округления в средней точке, кажется, что это хорошо работает. Однако возникает проблема, когда у этого числа есть последующие десятичные разряды, которые арифметически влияют на округление.
Пример:
С 0.1
, 0.11..0.19
и 0.141..0.44
это работает:
Math.Round(0.1, 1) == 0.1
Math.Round(0.11, 1) == 0.1
Math.Round(0.14, 1) == 0.1
Math.Round(0.15, 1) == 0.2
Math.Round(0.141, 1) == 0.1
Но с 0.141..0.149
всегда возвращается 0.1
, хотя 0.146..0.149
должно округляться до 0.2
:
Math.Round(0.145, 1, MidpointRounding.AwayFromZero) == 0.1
Math.Round(0.146, 1, MidpointRounding.AwayFromZero) == 0.1
Math.Round(0.146, 1, MidpointRounding.ToEven) == 0.1
Math.Round(0.146M, 1, MidpointRounding.ToEven) == 0.1M
Math.Round(0.146M, 1, MidpointRounding.AwayFromZero) == 0.1M
Я попытался придумать функцию, которая решает эту проблему, и она хорошо работает в этом случае, но, конечно, она гламурно не сработает, если вы попытаетесь округлить, т.е. 0.144449
, до первого десятичного знака (который должен быть 0.2
, но в результате 0.1
.) (Это также не работает с Math.Round ().)
private double "round"(double value, int digit)
{
// basically the old "add 0.5, then truncate to integer" trick
double fix = 0.5D/( Math.Pow(10D, digit+1) )*( value >= 0 ? 1D : -1D );
double fixedValue = value + fix;
// 'truncate to integer' - shift left, round, shift right
return Math.Round(fixedValue * Math.Pow(10D, digit)) / Math.Pow(10D, digit);
}
Я полагаю, что решением было бы перечислить все цифры, найти первое значение больше 4, а затем округлить вверх или округлить вниз. Проблема 1: Это кажется идиотским, Проблема 2: я понятия не имею, как перечислять цифры без десятка умножений и вычитаний.
Короче говоря: каков наилучший способ сделать это?