与前pression和分配的对象浮点不一致 [英] Floating point inconsistency between expression and assigned object

查看:148
本文介绍了与前pression和分配的对象浮点不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这让我吃惊 - 同样的算法给出了不同的结果,具体取决于其执行:

This surprised me - the same arithmetic gives different results depending on how its executed:

> 0.1f+0.2f==0.3f
False

> var z = 0.3f;
> 0.1f+0.2f==z
True

> 0.1f+0.2f==(dynamic)0.3f
True

(经过测试,在Linqpad)

(Tested in Linqpad)

这是怎么回事?

修改:我明白为什么浮点运算是IM precise,而不是它为什么会的不一致

Edit: I understand why floating point arithmetic is imprecise, but not why it would be inconsistent.

在古老的ç可靠证实的 0.1 + 0.2 = = 0.3 的保持着单precision花车,但不是双重precision浮动点。

The venerable C reliably confirms that 0.1 + 0.2 == 0.3 holds for single-precision floats, but not double-precision floating points.

推荐答案

我强烈怀疑你会发现你有和没有调试器中运行该code不同的结果,并在发布配置VS的调试配置。

I strongly suspect you may find that you get different results running this code with and without the debugger, and in release configuration vs in debug configuration.

在第一个版本中,你比较两个EX pressions。 C#语言允许那些EX pressions在更高的precision算术比源类型进行评估。

In the first version, you're comparing two expressions. The C# language allows those expressions to be evaluated in higher precision arithmetic than the source types.

在第二个版本,你分配相加结果到局部变量。 在某些情况下的,这将迫使结果被截断到32位 - 导致了不同的结果。在其他情况下,在CLR或C#编译器会认识到,它可以优化掉局部变量。

In the second version, you're assigning the addition result to a local variable. In some scenarios, that will force the result to be truncated down to 32 bits - leading to a different result. In other scenarios, the CLR or C# compiler will realize that it can optimize away the local variable.

从C#4规范的第4.1.6节:

From section 4.1.6 of the C# 4 spec:

浮点运算可与更高precision比运算的结果类型来执行。例如,一些硬件结构支持的扩展或长双浮点类型具有更大的范围和precision比键入,并含蓄地执行所有浮动浮点运算具有较高precision类型。只有在性能开销过大,才能使这样的硬件结构来执行浮点运算用的的precision。而不是需要实现丧失性能和precision,C#允许使用更高的precision类型所有浮点运算。除了提供更多的precise结果,这种情况很少会产生任何可察觉的影响。

Floating point operations may be performed with higher precision than the result type of the operation. For example, some hardware architectures support an "extended" or "long double" floating point type with greater range and precision than the double type, and implicitly perform all floating point operations with the higher precision type. Only at excessive cost in performance can such hardware architectures be made to perform floating point operations with less precision. Rather than require an implementation to forfeit both performance and precision, C# allows a higher precision type to be used for all floating point operations. Other than delivering more precise results, this rarely has any measurable effects.

编辑:我还没有尝试编译这一点,但在评论,克里斯说,第一种形式是不被计算在执行时都没有。以上可以的还是的应用(我已经调整了我的措辞略) - 它只是转移常量的评估时间从执行时间,编译时间。只要它的行为方式相同的的有效评估,这似乎还好我 - 所以编译器自身的不断EX pression评价可以用higher- precision算术太

I haven't tried compiling this, but in the comments, Chris says the first form isn't being evaluated at execution time at all. The above can still apply (I've tweaked my wording slightly) - it's just shifted the evaluation time of a constant from execution time to compile-time. So long as it behaves the same way as a valid evaluation, that seems okay to me - so the compiler's own constant expression evaluation can use higher-precision arithmetic too.

这篇关于与前pression和分配的对象浮点不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆