c#double值显示为.9999998?

时间:2013-08-06 06:56:47

标签: c# double rounding

经过进一步调查,这一切归结为:

(decimal)((object)my_4_decimal_place_double_value_20.9032)

投两次后,变为20.903199999999998


我有一个双精度值,通过Math.Round(...)四舍五入到4位小数,值为20.9032

在我的开发环境中,它按原样显示。

但在发布环境中,显示为20.903199999999998

Math.Round(...)之后没有任何操作,但该值已被复制并分配。

这怎么可能发生?

更新 数据未从DB加载。

Math.Round()的返回值分配给原始的双变量。

如果此信息有所帮助,则发布和开发是相同的体系结构。

2 个答案:

答案 0 :(得分:2)

根据CLR ECMA规范:

  

浮点数的存储位置(静态,数组元素,   和类的领域)是固定的大小。支持的存储大小   是float32和float64。其他地方(在评估堆栈上,作为   参数,返回类型和局部变量)浮点数   数字使用内部浮点类型表示。每个   例如,变量或表达式的名义类型是   R4或R8,但其值可以在内部表示   额外的范围和/或精度。内部的大小   浮点表示是依赖于实现的,可以变化,   并且应具有至少与变量或变量一样大的精度   表达被表达。隐含的扩展转换为   当执行float32或float64时的内部表示   这些类型是从存储加载的。内部表示是   通常是硬件的原生大小,或者根据需要   有效实施一项行动。

要翻译,生成的IL将是相同的(除了调试模式在地方插入nops以确保断点是可能的,它还可能故意维护一个临时变量,释放模式认为不必要。)...但是JITter处理标记为调试的程序集时不那么激进。版本构建倾向于将更多浮动值移动到80位寄存器中;调试版本倾向于直接从64位内存存储中读取。

如果您想要“精确”浮点数打印,请使用string.Substring(...)代替Math.Round

答案 1 :(得分:2)

IEEE754双精度浮点数不能代表20.9032。 最准确的表示形式是2.09031999999999982264853315428E1,这就是您在输出中看到的内容。

不要使用round格式化数字而是使用double.ToString(string formatString)方法的字符串格式。

参见Double.ToString Method(String)的msdn documentation

Release和Debug构建之间的区别可能是为发布版本做了一些优化,但这是我认为详细的方法。 在我看来,核心问题是你尝试使用数学运算格式化文本输出。对不起,我不知道具体是什么造成了不同的行为。