经过进一步调查,这一切归结为:
(decimal)((object)my_4_decimal_place_double_value_20.9032)
投两次后,变为20.903199999999998
我有一个双精度值,通过Math.Round(...)
四舍五入到4位小数,值为20.9032
在我的开发环境中,它按原样显示。
但在发布环境中,显示为20.903199999999998
Math.Round(...)
之后没有任何操作,但该值已被复制并分配。
这怎么可能发生?
更新 数据未从DB加载。
将Math.Round()
的返回值分配给原始的双变量。
如果此信息有所帮助,则发布和开发是相同的体系结构。
答案 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构建之间的区别可能是为发布版本做了一些优化,但这是我认为详细的方法。 在我看来,核心问题是你尝试使用数学运算格式化文本输出。对不起,我不知道具体是什么造成了不同的行为。