古怪的可空十进制精度行为
本文关键字:精度 十进制 | 更新日期: 2023-09-27 17:48:56
我在数据存储中有一些列使用12十进制精度。
我想将其四舍五入到4位,以便通过文本提要发送,而该提要的消费者需要x精度。
我正在使用自定义构建的工作流引擎,并且在执行的任何点都不能直接访问代码,但可以使用条件在任何字段上注入代码,例如:
if (obj.myValue.HasValue)
obj.myValue = System.Math.Round(obj.MyValue.Value, 4)
上面的例子可以进行舍入,但是在一些情况下,不删除后面的0。使用obj.myValue.ToString()(依此类推,适用于所有字段)自动生成的最终结果
这似乎只发生在可空的十进制字段上。
我不确定有什么不同,但在大约10%的行中,输出保留尾随0。实际值是四舍五入的,但0保持不变:
134.402100000000
我也试过这样做(只是为了确保并删除小数的初始精度)
if (obj.myValue.HasValue)
obj.myValue = decimal.Parse(obj.MyValue.Value.ToString("#.####"))
还是,有些行仍然以末尾的0结尾。
看起来好像属性被初始化为x位小数,和最终的ToString。
考虑到我没有直接访问这段代码,但可以注入任何c#在该属性上执行,还有其他的事情我可以尝试吗?(我还尝试硬编码所有行到一个值,这工作得很好w/out额外的0)
同样有趣的是,我不能在我的测试中重现这个行为。
decimal d1 = 160236194.3900000000000001M;
Console.WriteLine(d1);
d1 = Math.Round(d1, 4);
Console.WriteLine(d1);
160236194.3900000000000001
160236194.3900
Press any key to continue . . .
编辑尝试了另一种方法,感谢e.James(测试是否truncate会删除0)
if (obj.myValue.HasValue)
obj.myValue = decimal.Truncate(obj.MyValue.Value)
和. .截断适用于所有行,但是0仍然保留在那些具有先前!不同的是,这次只有0。在截断之前是8900000000等等。这太疯狂了!
有些十进制数不能用二进制格式完美地表示。你的obj.myValue
属性是一个十进制数。对于某些小数,它将无法存储除(例如)1234.4021000000000001之外的任何内容,这是有限位数下最接近的。
我认为Domenic的答案是正确的。让十进制数字在存储中保持不四舍五入,并且只显示四舍五入后的*。
如果您绝对必须存储四舍五入的数字,则必须使用整数格式,然后在显示之前将其除以1000。1234.4021将被存储为12344021。
*注:这里的"显示"是指"输出到文本",而不一定是"显示给用户"
为什么不让显示逻辑处理显示逻辑呢?也就是说,只有当您将decimal
显示为string
时,才需要关心显示的尾随0
的数量,在这种情况下,您应该使用theDecimal.ToString("#.####")
。