C#十进制舍入不一致吗?

Ben*_*ill 38 c# rounding

我一直在使用来自SQL Decimal(38,30)的C#中的十进制精度,我终于把它变成了一个舍入奇怪的东西.我知道我可能会忽视这里显而易见的事情,但我需要一点见解.

我遇到的问题是C#没有产生我认为是一致输出的东西.

decimal a = 0.387518769125m;
decimal b = 0.3875187691250002636113061835m;

Console.WriteLine(Math.Round(a, 11));
Console.WriteLine(Math.Round(b, 11));
Console.WriteLine(Math.Round(a, 11) == Math.Round(b, 11));
Run Code Online (Sandbox Code Playgroud)

产量

0.38751876912
0.38751876913
False
Run Code Online (Sandbox Code Playgroud)

嗯,0.38751876913?真?我在这里错过了什么?

来自MSDN:

如果小数位的数字是奇数,则将其更改为偶数.否则,它保持不变.

为什么我看到不一致的结果?额外的精度不会改变'小数位数'......

jas*_*son 45

来自MSDN:

如果有一个非零数字在d向右的的decimals小数点位置和它的价值是5,在小数位数字四舍五入,如果它是奇数,或保持不变,如果它是偶数.如果d小数位数少于decimals,d则返回不变.

在你的第一个案例

decimal a = 0.387518769125m;
Console.WriteLine(Math.Round(a, 11));
Run Code Online (Sandbox Code Playgroud)

第11位右边一位数字,而且这个数字是5.因此,由于位置11是偶数,所以它保持不变.因此,你得到

0.38751876912
Run Code Online (Sandbox Code Playgroud)

在你的第二个案件

decimal b = 0.3875187691250002636113061835m;
Console.WriteLine(Math.Round(b, 11));
Run Code Online (Sandbox Code Playgroud)

没有一个单一的数字移到右边第11位的.因此,这是直接的小学 - 学校四舍五入; 如果下一个数字大于4,则向上舍入,否则向下舍入.由于第11位右边的数字超过4(它是5),我们会向上看,所以你看

0.38751876913
Run Code Online (Sandbox Code Playgroud)

为什么我看到不一致的结果?

你不是.结果与文档完全一致.

  • @BennettDill"单个非零数字等于5"是一种令人困惑的方式,说"方法的参数正好在两个可能的返回值之间".如果*不是*指定位置右侧的单个数字,或者只有一个数字不是5,那么参数不完全在可能的返回值之间,因此您选择更接近于争论.啊,如果我们只使用3号基数,我们就不用担心了! (5认同)
  • 为了确保我在这里理解,ToEven或AwayFromZero根据数字的精确度作为默认值而变化? (2认同)

Ode*_*ded 26

从MSDN - Math.Round方法(十进制,Int32):

如果小数位小数点右边的d中有一个非零数字且其值为5,则小数位的数字如果是奇数则向上舍入,如果是偶数则保持不变.如果d的小数位数小于小数位数,则返回d不变.

此方法的行为遵循IEEE标准754第4节.这种舍入有时称为舍入到最近,或者是银行家的舍入.它最大限度地减少了在单个方向上始终舍入中点值所导致的舍入误差.

注意使用单个非零数字.这对应于您的第一个示例,但不是第二个示例.

和:

若要控制Round(Decimal,Int32)方法使用的舍入类型,请调用Decimal.Round(Decimal,Int32,MidpointRounding)重载.