假设我有这个程序:
#include <iostream>
using namespace std;
int main() {
unsigned int n, i;
double sum = 0;
cout << "\n No. of terms: ";
cin >> n;
for( i=1; i<=n; i++ ) {
sum += i/(i+1.0); //// THE LINE IN QUESTION
}
cout << " Sum = " << sum;
return 0;
}
它计算系列的总和:1/2 + 2/3 + 3/4 .. 到 n/n+1。
现在我想问一下,在我想将 int 值赋给双变量 sum 的 for 循环中,我可以通过两种方式做到这一点:
- 方法一:
sum += i/(i+1.0)
- 方法 2:
sum += (double) i/(i+1)
哪个更快或更好?
Lightth races in orbits :我的意思是应该使用哪种方法。
最佳答案
根据经验,此类微小差异可能无关紧要。在大约 20 个左右的周期(大部分由部门占用)中,有一个或两个周期的差异,如果有的话。
这些是您的两个方法执行的操作:
方法一
a = (double)i; // convert to double
b = 1.0; // load double
c = a + b; // double addition
sum = a / c; // double division
请注意,我们只需要对 double
进行一次转换,因为编译器可以进行称为公共(public)子表达式消除的优化。在许多机器(如 x86)上,您不能简单地将浮点常量添加到数字中,您必须先将常量加载到浮点寄存器中,因此我将其视为额外指令。如果您在循环中执行此操作,则 1.0
只需加载一次。
方法二
a = (double)i; // convert to double
b = i + 1; // int addition
c = (double)b; // convert to double
sum = a / c; // double division
这里我们需要做两次转换,但我们可以节省浮点负载,我们可以用更便宜的整数加法代替浮点加法。
机器码
这是两种方法的 amd64 汇编:
method1:
pxor %xmm0, %xmm0 // clear result register
movsd .one(%rip), %xmm1 // load 1.0
cvtsi2sd %edi, %xmm0 // convert int to double
addsd %xmm0, %xmm1 // double addition
divsd %xmm1, %xmm0 // double division
.one:
.double 1.0
method2:
pxor %xmm0, %xmm0 // clear result register
pxor %xmm1, %xmm1 // clear register for i + 1
cvtsi2sd %edi, %xmm0 // convert int to double
addl $1, %edi // increment
cvtsi2sd %edi, %xmm1 // convert int to double
divsd %xmm1, %xmm0 // double division
这两种方法在操作方面似乎相当相似。如果您想确定,我建议您对此进行基准测试。
关于c++ - 显式类型转换与使用类型规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32035761/