C++ 我必须使用 0.f 初始化浮点数吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12637581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Must I initialize floats using 0.f?
提问by bobobobo
When I initialize float
variables in my program, I commonly have vectors like:
当我float
在我的程序中初始化变量时,我通常有像这样的向量:
Vector forward(0.f,0.f,-1.f),right(1.f,0.f,0.f),up(0.f,1.f,0.f)
(Vectors are just 3 floats like struct Vector{ float x,y,z; };
)
(向量只是 3 个浮点数struct Vector{ float x,y,z; };
)
This looks mucheasier to read as:
这看起来更容易阅读:
Vector forward(0,0,-1),right(1,0,0),up(0,1,0)
Must I initialize my float
variables using float
s? Am I losing anything or incurring some kind of penalty when I use integers (or double
s) to initialize a float
?
我必须float
使用float
s初始化我的变量吗?当我使用整数(或double
s)初始化 a时,我是否会丢失任何东西或招致某种惩罚float
?
回答by Mihai Maruseac
There's no semantic difference between the two. Depending on some compilers, it is possible for extra code to be generated, though. See also thisand thisSO questions of the same topic.
两者之间没有语义差异。但是,根据某些编译器,可能会生成额外的代码。另请参阅同一主题的此和此SO 问题。
I can confirm that gcc
generates the same code for all variants of
我可以确认gcc
为所有变体生成相同的代码
int main()
{
float a = 0.0f; /* or 0 or 0.0 */
return 0;
}
and that this code is
并且这段代码是
.file "1.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl movl movl float x = 0;
float x = 0.0;
float x = 0.0f;
float x = 0.0L; // converted from long double to float
x3dcccccd, %eax
x00000000, %eax
x00000000, %eax
movl %eax, -4(%rbp)
movl float x = 1 / 2;
, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
.section .note.GNU-stack,"",@progbits
The relevant line is
相关行是
##代码##Changing a
to 0.1
(or 0.1f
) changes the line to
更改a
为0.1
(或0.1f
) 将行更改为
It seems that gcc
is able to deduce the correct constant and doesn't generate extra code.
似乎gcc
能够推导出正确的常量并且不会生成额外的代码。
回答by Keith Thompson
For a single literal constant, it shouldn't matter. In the context of an initializer, a constant of any numeric type will be implicitly converted to the type of the object being initialized. This is guaranteed by the language standard. So all of these:
对于单个文字常量,它应该无关紧要。在初始化程序的上下文中,任何数字类型的常量都将隐式转换为正在初始化的对象的类型。这是由语言标准保证的。所以所有这些:
##代码##are equally valid and result in the same value being stored in x
.
同样有效并导致相同的值存储在x
.
A literal constant in a more complex expression can have surprising results, though.
但是,更复杂表达式中的文字常量可能会产生令人惊讶的结果。
In most cases, each expression is evaluated by itself, regardless of the context in which it appears. Any implicit conversion is applied afterthe subexpression has been evaluated.
在大多数情况下,每个表达式都会自行计算,而不管它出现在什么上下文中。在评估子表达式后应用任何隐式转换。
So if you write:
所以如果你写:
##代码##the expression 1 / 2
will be evaluated as an int
, yielding 0
, which is then converted to float. It will set
xto
0.0f, not to
0.5f`.
表达式1 / 2
将被计算为一个int
, yielding 0
,然后转换为float. It will set
x to
0.0f , not to
0.5f`。
I think you should be safe using unsuffixed floating-point constants (which are of type double
).
我认为使用无后缀的浮点常量(类型为double
)应该是安全的。
Incidentally, you might consider using double
rather than float
in your program. double
, as I mentioned, is the type of an unsuffixed floating-point constant, and can be thought of in some sense as the "default" floating-point type. It usually has more range and precision than float
, and there's typically not much difference in performance.
顺便说一句,您可能会考虑使用double
而不是float
在您的程序中。double
,正如我所提到的,是无后缀浮点常量的类型,在某种意义上可以被认为是“默认”浮点类型。它通常比 具有更大的范围和精度float
,并且通常在性能上没有太大差异。
回答by JustMy2Cents
It could be a good programming practise to always write 0.f, 1.f etc., even if oftengcc can figure out what the programmer means by 1.0 et al.
始终编写 0.f、1.f 等可能是一个很好的编程习惯,即使gcc经常可以通过 1.0 等来弄清楚程序员的意思。
The problematic cases are not so much trivial float variable initializations, but numeric constants in somewhat more complex formulae, where a combination of operators, float variables and said constants can easily lead to occurrence of unintended double valued calculations and costly float-double-float conversions.
有问题的情况不是很多琐碎的浮点变量初始化,而是更复杂的公式中的数字常量,其中运算符、浮点变量和所述常量的组合很容易导致意外双值计算和代价高昂的浮点双浮点转换的发生.
Spotting these conversions without specifically checking the compiled code for them becomes very hard if the intended type for numeric values is mostly omitted in the code and instead only included when it's absolutely required. Hence I for one would choose the approach of just typing in the f's and getting used to having them around.
如果数字值的预期类型在代码中大部分被省略而仅在绝对需要时才包含,那么在不专门检查编译代码的情况下发现这些转换变得非常困难。因此,我会选择只输入 f 并习惯于让它们在身边的方法。