浮点数的乘法与除法运算耗时对比
一.浮点数运算概述
1.浮点数采用IEEE 754标准表示实数,由三部分组成:
[符号位 S][指数位 E][尾数位 M]
例如双精度浮点数(double):
总位数:64位
符号位:1位
指数位:11位(范围 -1022 ~ 1023)
尾数位:52位(有效精度约15位小数)
2.浮点运算(Floating-Point Operation)指对浮点数进行的算术计算。
二.除法 vs 乘法耗时对比
1.在处理器中,double类型除法比乘法显著更慢:
2.性能差异根源
硬件实现差异:
乘法器:采用并行树形结构(如Wallace树)
除法器:依赖迭代算法(牛顿-拉夫森法或SRT算法)
计算复杂度:
乘法:$O(n^2)$(n为位数)
除法:$O(n^2 \log n)$ 或更高
流水线限制:
除法无法充分流水化,导致吞吐量下降
3.实测数据
// 42亿次乘法:≈1.9秒
for(int i=0; i<0xffffffff; i++) result = (double)i * 1556.368;
// 42亿次除法:≈3.7秒 (慢2倍)
for(int i=0; i<0xffffffff; i++) result = (double)i / 1556.368;
三.除法转乘法的优化技术
1. 倒数乘法(最常用)
// 原始除法
double y = x / c;
// 优化为乘法
double inv_c = 1.0 / c; // 预先计算倒数
double y = x * inv_c; // 循环中仅需乘法
适用场景:
分母c在循环中恒定不变
可容忍轻微精度损失(约1 ULP误差)
2.牛顿迭代法求倒数
当需要更高精度时:
// 牛顿迭代求倒数 (双精度)
double rcp_newton(double b) {
double y = 1.0 / b; // 初始近似值
y = y * (2.0 - b * y); // 第1次迭代
y = y * (2.0 - b * y); // 第2次迭代 (精度达~50位)
return y;
}
// 使用
double inv_b = rcp_newton(b);
double result = a * inv_b;
迭代次数与精度关系:
3.FMA(乘加)加速示例
double rcp_fma(double b) {
double y = 1.0 / b;
y = fma(y, fma(-b, y, 2.0), 0.0);
return y;
}
4.总结