大卫的评论是正确的,但不够有力。不能保证 在同一程序中两次 执行该计算会产生相同的结果。
在这一点上,C#规范非常清晰:
浮点运算可以比运算的结果类型更高的精度执行。例如,某些硬件体系结构支持比双精度类型具有更大范围和精度的“扩展”或“长双精度”浮点类型,并使用此更高精度类型隐式执行所有浮点运算。只有付出过高的性能代价,才能使此类硬件体系结构以较低的精度执行浮点运算,而不是要求实现同时牺牲性能和精度,而C#允许将高精度类型用于所有浮点运算。
。除了提供更精确的结果外,这几乎没有任何可测量的效果。但是,在以下形式的表达式中x * y /z,如果相乘产生的结果超出双精度范围,但是随后的除法将暂时结果带回双精度范围,那么以较高范围格式计算表达式的事实可能会导致产生有限结果,而不是无限
C#编译器,抖动和运行时都具有宽广的纬度,可以随时随地为您提供比规范要求 更准确的结果 -不需要选择一致地这样做,事实上,它们确实可以不。
如果您不喜欢这样做,请不要使用二进制浮点数。使用小数或任意精度有理数。
我不明白为什么在返回float的方法中强制转换为float会有所不同
优点。
您的示例程序演示了微小的变化如何导致较大的影响。您会注意到,在某些版本的运行时中,强制转换为float会得出与未执行的结果不同的结果。
当您显式转换为float时,C#编译器会提示运行时 说:“如果碰巧正在使用此优化,则将其退出超高精度模式”。如规范所指出的,
这有潜在的性能成本。
这样做会凑合到“正确答案”,这仅仅是一个偶然的意外;之所以能找到正确的答案,是因为在这种情况下, 精度的损失恰恰导致了在正确方向上的损失 。
.net 4有何不同?
您问3.5和4.0运行时之间有什么区别;区别很明显,在4.0中,在特定情况下,抖动选择精度更高,而3.5抖动则选择不精度。这并不意味着在3.5中是不可能的。在运行时的每个版本和C#编译器的每个版本中都可以实现。您碰巧遇到了一个案例,在您的计算机上,它们的详细信息不同。但是
始终 允许抖动来进行此优化,并且总是一时兴起。
当在编译时计算常量浮点数时,C#编译器完全有权选择进行类似的优化。根据编译器运行时状态的详细信息,常量中的两个看似相同的计算可能会得出不同的结果。
更普遍地,您对浮点数应该具有实数的代数性质的期望与现实完全不符。他们没有那些代数性质。浮点运算甚至没有 关联
;他们当然不遵守您所期望的乘法逆定律。浮点数仅是实数的近似值。一种近似值,足以模拟物理系统,计算摘要统计信息或类似的东西。



