很久以前,在一本有关古代FORTRAN的书中,我看到过这样的说法:将整数常量与浮点变量一起使用会比较慢,因为首先需要将常量转换为浮点形式:
double a = ..;
double b = a*2; // 2 -> 2.0 first
double c = a*2.0;
在现代C++中编写2.0而不是2仍然有益吗?如果不是这样,可能应该首选“整数版本”,因为2.0更长,并且对人类读者没有任何影响。
我使用复杂的长表达式,这些表达式中的“.0”会影响性能或可读性(如果有的话)。
最佳答案
原始问题:
让我们比较一下程序集的输出。
double foo(double a)
{
return a * 2;
}
double bar(double a)
{
return a * 2.0f;
}
double baz(double a)
{
return a * 2.0;
}
结果是
0000000000000000 <foo>: //double x int
0: f2 0f 58 c0 addsd %xmm0,%xmm0 // add with itself
4: c3 retq // return (quad)
5: 90 nop // padding
6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) // padding
d: 00 00 00
0000000000000010 <bar>: //double x float
10: f2 0f 58 c0 addsd %xmm0,%xmm0 // add with itself
14: c3 retq // return (quad)
15: 90 nop // padding
16: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) // padding
1d: 00 00 00
0000000000000020 <baz>: //double x double
20: f2 0f 58 c0 addsd %xmm0,%xmm0 // add with itself
24: c3 retq // return (quad)
如您所见,它们都是相等的,根本不执行乘法。
即使进行实数乘法(
a*5
),它们也都相等,并且执行到0: f2 0f 59 05 00 00 00 mulsd 0x0(%rip),%xmm0 # 8 <foo+0x8>
7: 00
8: c3 retq
加成:
@ Goswin-Von-Brederlow说,使用非常量表达式将导致不同的汇编。让我们像上面的例子那样测试它,但是带有以下签名。
double foo(double a, int b); //int, float, double for foo/bar/baz
导致输出:
0000000000000000 <foo>: //double x int
0: 66 0f ef c9 pxor %xmm1,%xmm1 // clear xmm1
4: f2 0f 2a cf cvtsi2sd %edi,%xmm1 // convert edi (second argument) to double
8: f2 0f 59 c1 mulsd %xmm1,%xmm0 // mul xmm1 with xmm0
c: c3 retq // return
d: 0f 1f 00 nopl (%rax) // padding
0000000000000010 <bar>: //double x float
10: f3 0f 5a c9 cvtss2sd %xmm1,%xmm1 // convert float to double
14: f2 0f 59 c1 mulsd %xmm1,%xmm0 // mul
18: c3 retq // return
19: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) // padding
0000000000000020 <baz>: //double x double
20: f2 0f 59 c1 mulsd %xmm1,%xmm0 // mul directly
24: c3 retq // return
在这里,您可以看到(运行时)从类型到 double 类型的转换,这当然会导致(运行时)开销。
关于c++ - 假设a是两倍,2.0 * a比2 * a快吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51261457/