浮动增加了两倍? [英] Float addition promoted to double?

查看:107
本文介绍了浮动增加了两倍?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

今天早上我有一个小的WTF时刻。可以这样总结一下WTF:

  float x = 0.2f; 
float y = 0.1f;
float z = x + y;
assert(z == x + y); //这个断言被触发! (atleast with visual studio 2008)

原因似乎是表达式 x + y 被提升为双倍,并与 z 中的截断版本进行比较。 (如果我将 z 更改为 double 则不会触发该断言。)



我可以看到,为了精确的原因,在将结果转换为单精度之前,以双精度执行所有浮点算术是有意义的。我在标准中找到了以下段落(我猜想我已经知道了,但不是在这种情况下):



4.6.1。
类型为 float 的值可以转换为类型为 double 的值,值为不变



我的问题是,是 x + y 保证升格为双倍,或是在编译器的酌情权?



更新:由于很多人声称不应该使用 == 对于浮点数,我只想说明在具体情况下,我正在使用,确切的比较是有道理的。



浮点比较棘手,这是一个有趣的链接关于我认为没有的主题

解决方案

你通常不会假设 == 工作预计浮点类型。比较四舍五入的值或使用结构,如 abs(a-b)容忍



促销完全由编译器自行决定(并将取决于目标硬件,优化级别等)。



在这种特殊情况下,发生的事情几乎肯定是以比内存更高的精度将值存储在FPU寄存器中 - 一般来说,现代FPU硬件可以使用双倍或编程器要求的精度在内部更高的精度,编译器生成代码以在值存储到存储器时进行适当的转换;在未优化的版本中, x + y 的结果仍然在注册表中,但是进行比较,但$ code> z 将被存储到内存中并被取回,从而被截断以浮动精度。


I had a small WTF moment this morning. Ths WTF can be summarized with this:

float x = 0.2f;
float y = 0.1f;
float z = x + y;
assert(z == x + y); //This assert is triggered! (Atleast with visual studio 2008)

The reason seems to be that the expression x + y is promoted to double and compared with the truncated version in z. (If i change z to double the assert isn't triggered).

I can see that for precision reasons it would make sense to perform all floating point arithmetics in double precision before converting the result to single precision. I found the following paragraph in the standard (which I guess I sort of already knew, but not in this context):

4.6.1. "An rvalue of type float can be converted to an rvalue of type double. The value is unchanged"

My question is, is x + y guaranteed to be promoted to double or is at the compiler's discretion?

UPDATE: Since many people has claimed that one shouldn't use == for floating point, I just wanted to state that in the specific case I'm working with, an exact comparison is justified.

Floating point comparision is tricky, here's an interesting link on the subject which I think hasn't been mentioned.

解决方案

You can't generally assume that == will work as expected for floating point types. Compare rounded values or use constructs like abs(a-b) < tolerance instead.

Promotion is entirely at the compiler's discretion (and will depend on target hardware, optimisation level, etc).

What's going on in this particular case is almost certainly that values are stored in FPU registers at a higher precision than in memory - in general, modern FPU hardware works with double or higher precision internally whatever precision the programmer asked for, with the compiler generating code to make the appropriate conversions when values are stored to memory; in an unoptimised build, the result of x+y is still in a register at the point the comparison is made but z will have been stored out to memory and fetched back, and thus truncated to float precision.

这篇关于浮动增加了两倍?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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