Rz *_* Mk 53 .net c# floating-point casting .net-4.0
为什么此代码False在.NET 4中打印?似乎一些意外的行为是由显式演员引起的.
我想要一个超越"浮动点不准确"或"不要那样做"的答案.
float a(float x, float y)
{
return ( x * y );
}
float b(float x, float y)
{
return (float)( x * y );
}
void Main()
{
Console.WriteLine( a( 10f, 1f/10f ) == b( 10f, 1f/10f ) );
}
Run Code Online (Sandbox Code Playgroud)
PS:此代码来自单元测试,而不是发布代码.代码是故意以这种方式编写的.我怀疑它最终会失败,但我想知道确切的时间和原因.答案证明了这种技术的有效性,因为它提供的理解超出了对浮点确定性的通常理解.这就是用这种方式编写代码的重点; 刻意探索.
PPS:单元测试在.NET 3.5中传递,但现在在升级到.NET 4后失败了.
Eri*_*ert 82
大卫的评论是正确的,但不够强大.无法保证在同一程序中进行两次计算会产生相同的结果.
在这一点上,C#规范非常明确:
可以以比操作的结果类型更高的精度执行浮点运算.例如,某些硬件体系结构支持"扩展"或"长双"浮点类型,其范围和精度比double类型更大,并使用此更高精度类型隐式执行所有浮点运算.只有在性能成本过高的情况下,才能使这种硬件架构以较低的精度执行浮点运算,而不是要求实现放弃性能和精度,C#允许更高精度的类型用于所有浮点运算.除了提供更精确的结果外,这几乎没有任何可衡量的影响.但是,在表单的表达式中
x * y / z,乘法产生的结果超出双范围,但随后的除法将临时结果带回双范围,表达式以更高范围格式计算的事实可能导致产生有限结果而不是无穷大.
C#编译器,抖动和运行时都具有广泛的优势,可以随时随地为您提供比规范要求更准确的结果 - 他们不需要选择一致地执行此操作,事实上他们这样做不.
如果您不喜欢,请不要使用二进制浮点数; 要么使用小数,要么使用任意精度.
我不明白为什么在一个返回float的方法中使用float进行浮动会产生差异
优点.
您的示例程序演示了小的更改如何导致大的效果.您注意到在某些版本的运行时中,显式转换为float会产生与不这样做不同的结果.当你明确地转换为float时,C#编译器会给运行时提供一个提示,说"如果碰巧使用这个优化,就把这个东西从超高精度模式中取出".如规范所述,这具有潜在的性能成本.
这样做恰好围绕"正确答案"只是一个幸福的事故; 得到了正确的答案,因为在这种情况下失去精确度恰好在正确的方向上失去了它.
.net 4有何不同?
你问3.5和4.0运行时间有什么区别; 差别很明显,在4.0中,抖动选择在特定情况下达到更高的精度,3.5抖动选择不.这并不意味着这种情况在3.5中是不可能的; 它可以在每个版本的运行时和每个版本的C#编译器中使用.你碰巧碰到的情况是,在你的机器上,他们的细节不同.但是,抖动一直被允许进行这种优化,并始终如此突发奇想.
在编译时计算常量浮点数时,C#编译器完全有权选择进行类似的优化.根据编译器的运行时状态的详细信息,常量中两个看似相同的计算可能会有不同的结果.
更一般地说,你期望浮点数应该具有实数的代数性质,这与现实完全不符; 他们没有那些代数属性.浮点运算甚至不是关联的 ; 他们当然不会像你期望的那样遵守乘法逆的定律.浮点数只是实数算术的近似值; 一个足够接近的近似值,比如模拟物理系统,或计算汇总统计数据,或某些此类事物.
| 归档时间: |
|
| 查看次数: |
5133 次 |
| 最近记录: |