我正在尝试将一个数字四舍五入到小数点后的第一位,并且考虑到不同的 MidpointRounding 选项,这似乎效果很好。但是,当该数字具有随后的小数位时,就会出现一个问题,这会在算术上影响四舍五入。
一个例子:
,它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
我试图想出一个解决这个问题的函数,它在这种情况下效果很好,但是如果你尝试将 ie 四舍五入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:我不知道如何在没有大量乘法和减法的情况下枚举数字。
长话短说:最好的方法是什么?