【问题标题】:Must I initialize floats using 0.f?我必须使用 0.f 初始化浮点数吗?
【发布时间】:2012-09-28 09:47:15
【问题描述】:

当我在我的程序中初始化 float 变量时,我通常有如下向量:

Vector forward(0.f,0.f,-1.f),right(1.f,0.f,0.f),up(0.f,1.f,0.f)

(向量只是 3 个浮点数,例如 struct Vector{ float x,y,z; };

这看起来 更容易阅读:

Vector forward(0,0,-1),right(1,0,0),up(0,1,0)

我必须使用floats 初始化我的float 变量吗?当我使用整数(或 doubles)初始化 float 时,我是否会丢失任何东西或招致某种惩罚?

【问题讨论】:

  • 您不应该真正使用 Vector 作为结构名称,因为这很容易与 stl::vector 混淆。您可以改为将其命名为 vector3f 或 vector3d
  • 在 FORTRAN 中,您必须使用适当的分配,因此零双精度必须是 0.0d0,而不是 0.0e0 或 0。很多以 FORTRAN 开头的人都被这种行为所困扰并明确地将 0 .f 在他们的 C++ 代码中。相比之下,C++ 实际上指定了如何将文字 0 或 1 提升为适当的浮点值。
  • 我认为初始化不会是问题。但是,如果您进行比较,将使用更大的数据类型(0.0f 对 0.0),因此它往往会更慢。显然取决于用例,但没有使用正确的类型,您肯定会导致转换。编译时或运行时。避免它可以节省时间。

标签: c++ variables initialization


【解决方案1】:

两者之间没有语义差异。但是,根据某些编译器,可能会生成额外的代码。另请参阅 thisthis 同一主题的 SO 问题。

我可以确认gcc 为所有变体生成相同的代码

int main()
{
    float a = 0.0f; /* or 0 or 0.0 */
    return 0;
}

而且这段代码是

    .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    $0x00000000, %eax
    movl    %eax, -4(%rbp)
    movl    $0, %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

相关行是

    movl    $0x00000000, %eax

a 更改为0.1(或0.1f)会将行更改为

    movl    $0x3dcccccd, %eax

看来gcc 能够推导出正确的常数并且不会产生额外的代码。

【讨论】:

    【解决方案2】:

    对于单个文字常量,这无关紧要。在初始化器的上下文中,任何数字类型的常量都将隐式转换为正在初始化的对象的类型。这是由语言标准保证的。所以所有这些:

    float x = 0;
    float x = 0.0;
    float x = 0.0f;
    float x = 0.0L;   // converted from long double to float
    

    同样有效并导致将相同的值存储在x中。

    不过,更复杂的表达式中的文字常量可能会产生令人惊讶的结果。

    在大多数情况下,每个表达式都是由自身计算的,而不管它出现在什么上下文中。任何隐式转换都会在子表达式被求值之后应用。

    所以如果你写:

    float x = 1 / 2;
    

    表达式1 / 2 将被评估为int,产生0,然后转换为float. It will setxto0.0f, not to0.5f`。

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

    顺便说一句,您可以考虑在程序中使用double 而不是floatdouble,正如我所提到的,是无后缀浮点常量的类型,在某种意义上可以被认为是“默认”浮点类型。它通常比float 具有更大的范围和精度,并且通常在性能上没有太大差异。

    【讨论】:

      【解决方案3】:

      始终编写 0.f、1.f 等可能是一种很好的编程习惯,即使 经常 gcc 可以弄清楚程序员所说的 1.0 等是什么意思。

      有问题的情况不是微不足道的浮点变量初始化,而是更复杂的公式中的数字常量,其中运算符、浮点变量和所述常量的组合很容易导致意外的双值计算和代价高昂的浮点双精度-float 转换。

      如果代码中大部分都省略了数值的预期类型,而仅在绝对需要时才包含这些转换,那么在不专门检查它们的编译代码的情况下发现这些转换变得非常困难。因此,我会选择只输入 f 并习惯于使用它们的方法。

      【讨论】:

        猜你喜欢
        • 2021-09-13
        • 1970-01-01
        • 1970-01-01
        • 2017-03-13
        • 2020-04-30
        • 1970-01-01
        • 2010-11-05
        • 2023-03-24
        • 1970-01-01
        相关资源
        最近更新 更多