我们通常应该使用浮点字面量来代替更简单的双精度字面值吗?

2022-01-09 00:00:00 floating-point literals double c++

在 C++ 中 (或者可能只有我们的编译器 VC8 和 VC10) 3.14 是一个双精度字面值,而 3.14f 是一个浮点数字面量.

In C++ (or maybe only our compilers VC8 and VC10) 3.14 is a double literal and 3.14f is a float literal.

现在我有个同事说:

我们应该在浮点计算中使用浮点文字,在双精度计算中使用双文字,因为当在计算中使用常量时,这可能会影响计算的精度.

We should use float-literals for float calculations and double-literals for double calculations as this could have an impact on the precision of a calculation when constants are used in a calcualtion.

具体来说,我认为他的意思是:

Specifically, I think he meant:

double d1, d2;
float f1, f2;
... init and stuff ...
f1 = 3.1415  * f2;
f1 = 3.1415f * f2; // any difference?
d1 = 3.1415  * d2;
d1 = 3.1415f * d2; // any difference?

或者,由我添加,甚至:

Or, added by me, even:

d1 = 42    * d2;
d1 = 42.0f * d2; // any difference?
d1 = 42.0  * d2; // any difference?

更一般地说,我可以看到使用 2.71828183f 的 only 点是确保我尝试指定的常量实际上适合浮点数(编译器错误/警告).

More generally, the only point I can see for using 2.71828183f is to make sure that the constant I'm trying to specify will actually fit into a float (compiler error/warning otherwise).

有人可以解释一下吗?您是否指定 f 后缀?为什么?

Can someone shed some light on this? Do you specify the f postfix? Why?

引用一个我认为理所当然的答案:

To quote from an answer what I implicitly took for granted:

如果你正在使用一个浮点变量和一个双字面值操作将以双精度完成,然后转换回浮点数.

If you're working with a float variable and a double literal the whole operation will be done as double and then converted back to float.

这可能有什么危害吗?(除了非常非常理论上的性能影响?)

Could there possibly be any harm in this? (Other than a very, very theoretical performance impact?)

进一步如果包含技术细节的答案(赞赏!)还可以包括这些差异如何影响通用代码,那就太好了.(是的,如果您正在处理数字,您可能希望确保您的 big-n 浮点运算尽可能高效(和正确)――但是对于被调用几次的通用代码是否重要?是吗?如果代码只使用 0.0 并跳过 --hard to maintain! -- float 后缀,它会更干净吗?)

Further edit: It would be nice if answers containing technical details (appreciated!) could also include how these differences affect general purpose code. (Yes, if you're number crunching, you probably like to make sure your big-n floating point ops are as efficient (and correct) as possible -- but does it matter for general purpose code that's called a few times? Isn't it cleaner if the code just uses 0.0 and skips the -- hard to maintain! -- float suffix?)

推荐答案

是的,你应该使用 f 后缀.原因包括:

Yes, you should use the f suffix. Reasons include:

  1. 性能.当你写 float foo(float x) { return x*3.14;},您强制编译器发出将 x 转换为双精度的代码,然后进行乘法运算,然后将结果转换回单精度.如果添加 f 后缀,则两种转换都将被消除.在许多平台上,每一次这些转换都与乘法本身一样昂贵.

  1. Performance. When you write float foo(float x) { return x*3.14; }, you force the compiler to emit code that converts x to double, then does the multiplication, then converts the result back to single. If you add the f suffix, then both conversions are eliminated. On many platforms, each those conversions are about as expensive as the multiplication itself.

性能(续).在某些平台(例如大多数手机)上,双精度运算比单精度运算要慢得多.即使忽略转换开销(在 1. 中介绍),每次强制计算以双倍计算时,都会减慢程序速度.这不仅仅是一个理论"问题.

Performance (continued). There are platforms (most cellphones, for example), on which double-precision arithmetic is dramatically slower than single-precision. Even ignoring the conversion overhead (covered in 1.), every time you force a computation to be evaluated in double, you slow your program down. This is not just a "theoretical" issue.

减少您接触错误的机会.考虑示例 float x = 1.2;if (x == 1.2)//something; something 执行了吗?不,它不是,因为 x 保存 1.2 舍入为 float,但正在与双精度值 1.2 进行比较.两者不相等.

Reduce your exposure to bugs. Consider the example float x = 1.2; if (x == 1.2) // something; Is something executed? No, it is not, because x holds 1.2 rounded to a float, but is being compared to the double-precision value 1.2. The two are not equal.

相关文章