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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 16:27:40  来源:igfitidea点击:

Must I initialize floats using 0.f?

c++variablesinitialization

提问by bobobobo

When I initialize floatvariables 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 floatvariables using floats? Am I losing anything or incurring some kind of penalty when I use integers (or doubles) to initialize a float?

我必须float使用floats初始化我的变量吗?当我使用整数(或doubles)初始化 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 gccgenerates 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 ato 0.1(or 0.1f) changes the line to

更改a0.1(或0.1f) 将行更改为

##代码##

It seems that gccis 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 / 2will be evaluated as an int, yielding 0, which is then converted to float. It will setxto0.0f, not to0.5f`.

表达式1 / 2将被计算为一个int, yielding 0,然后转换为float. It will setx to0.0f , not to0.5f`。

I think you should be safe using unsuffixed floating-point constants (which are of type double).

我认为使用无后缀的浮点常量(类型为double)应该是安全的。

Incidentally, you might consider using doublerather than floatin 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 并习惯于让它们在身边的方法。