Math.Round在不同的运行环境中会产生不同的结果

3
我有一行代码,它产生了两个不同的结果。
给定以下行:
var rounded = Math.Round(415 * 0.01f, 1);

我期望这个值始终四舍五入为4.2。当我从控制台应用程序运行此代码时,总是得到预期结果4.2。如果我将相同的代码放入单元测试并运行该测试,结果会变成4.1。如果该代码在Windows服务中运行,结果也会是4.1。
您有什么想法可以解释为什么会产生不同的值或如何使其始终表现一致?
在64位机器上使用Visual Studio 2013和.NET 4.5运行此代码。

一点头绪都没有。看起来这个调用重定向到一个外部函数,可能与此有关。 - BradleyDotNET
1
当舍入中点值时,舍入算法执行等式测试。由于浮点格式中的二进制表示和精度问题,该方法返回的值可能是意外的。有关更多信息,请参阅Rounding and precision。https://msdn.microsoft.com/en-us/library/system.math.round(v=vs.110).aspx#Precision - Jesus Angulo
1
当我在控制台应用程序中尝试这段代码时,我得到的结果是 4.1。我认为问题在于你期望计算结果恰好是 4.15,但实际上它并不是。由于 0.01f 并不完全等于 0.01 而是等于 0.00999999977648258,所以结果是 4.14999990724027。如果你使用 Math.Round(4.15, 1),你将得到 4.2 - Guffa
Jesus的评论看起来不错,另外需要注意的是,我尝试使用固定点值(0.01m)进行计算,得到了预期的4.2而不是4.1。 - John Smith
@iliketocode 十进制是精确的。如果必须使用,请使用它们。 - SimpleVar
为了解释值在不同运行中的差异,您是否在任何一个运行期间附加了调试器?不同的配置,Release vs Debug 或 AnyCpu(带或不带 Prefer x86)或特定架构? - Ani
3个回答

0

许多年前,我也遇到了类似的问题。在启动我的应用程序后不久,它会使用一种精度计算双精度值,而过一段时间后则会使用另一种精度。这非常奇怪。

经过一段时间的研究,我发现某个时刻应用程序使用默认标志初始化DirectX,而DX则会改变双精度值的FPU精度。

因此,作为建议,请检查您相邻的代码是否有副作用。 (检查DirectX的使用,检查外部未托管的DLL的使用)

附言:没有魔法。不要被困惑。并尝试推迟使用Decimal。这是OLE中最慢的东西...


0

看起来控制台和测试运行器使用不同的首选舍入方式。

这应该给你相同的结果:

var rounded = Math.Round(415 * 0.01f, 1, MidpointRounding.AwayFromZero);

-1
var rounded = Math.Round(415 * 0.01d, 1);

你可以使用双精度类型替代单精度类型

精度不足


双精度浮点数也是浮点数值 - https://msdn.microsoft.com/zh-cn/library/678hzkk9.aspx - John Smith

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接