sun*_*ide 6 .net c# math bankers-rounding rounding
我试图将一个数字舍入到它的第一个小数位,考虑到不同的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
Run Code Online (Sandbox Code Playgroud)
但随着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
Run Code Online (Sandbox Code Playgroud)
我试图提出一个解决这个问题的函数,并且它适用于这种情况,但当然如果你尝试舍入即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);
}
Run Code Online (Sandbox Code Playgroud)
我假设一个解决方案是枚举所有数字,找到大于4的第一个值然后向上舍入,否则向下舍入.问题1:这似乎是愚蠢的,问题2:我不知道如何在没有大量乘法和减法的情况下枚举数字.
长话短说:最好的方法是什么?
Ste*_*ngs 20
Math.Round() 表现正常.
当您执行标准中点舍入时,您永远不需要超出您要四舍五入的位置之外的1位十进制数.如果你四舍五入到最接近的十分之一,那么你永远不需要超越小数点后的第二个数字.
中点舍入的想法是,中间数字的一半应该向上舍入,一半应该向下舍入.因此,对于介于0.1和0.2之间的数字,其中一半应该舍入到0.1,一半应该舍入到0.2.这两个数字之间的中点是0.15,因此这是四舍五入的阈值.0.146小于0.15,因此必须向下舍入到0.1.
Midpoint
0.10 0.15 0.20
|----------------|----|---------------------|
0.146
<---- Rounds Down
Run Code Online (Sandbox Code Playgroud)
ano*_*ard 15
我不知道你想要在这里完成什么.舍入到小数点后一位的0.149 为 0.1,而不是0.2
舍入不是一个迭代过程,你只绕一次.
所以0.146舍入到1个十进制数是 0.1.
你不这样做:
0.146 --> 0.15
0.15 --> 0.2
Run Code Online (Sandbox Code Playgroud)
你只这样做:
0.146 --> 0.1
Run Code Online (Sandbox Code Playgroud)
否则,以下内容:
0.14444444444444446
Run Code Online (Sandbox Code Playgroud)
也会圆到0.2,但它不会,也不应该.
不要试图复合舍入'错误'.这是你想要做的.
如果你要去小数点后一位,.146 应该向下舍入到.1.
首先将其四舍五入为.15,然后再将其舍入为.2,您只是引入了更多的舍入误差,而不是更少.
| 归档时间: |
|
| 查看次数: |
2705 次 |
| 最近记录: |