二进制除法转乘法原理
来源:互联网 发布:淘宝有什么好看的衣服 编辑:程序博客网 时间:2024/05/21 10:09
为了加快运行速度,编译器会将一些除法运算转化成乘法运算。
其中一个转换x/k的方法是,先将k变成1/k 的小数形式,再将1/k 左移N位
得到一个数b
以后每计算 x/k 时,就先计算 x∗b的乘积,再将乘积右移N位得到结果,这样就把耗时的除法运算变成了一个乘法和一个右移运算。
原理:
原理:
下面是一段测试C代码以及编译器生成的汇编代码:计算变量除以17的值
void test (){ int num = 18; int res = num/17; printf("res:%d\n",res);}
##计算num/17 pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 subq $16, %rsp movl $18, -8(%rbp) movl -8(%rbp), %ecx # %ecx=18 movl $2021161081, %edx # 2021161081 ≈ (1/17)*2^35 movl %ecx, %eax # %eax=%ecx=18 imull %edx # 计算2021161081*18的值,并将乘积的高32位存到%edx里。此时%edx的值相当于乘积右移32位后的值 sarl $3, %edx #将%edx的值算术右移3位,即乘积总共右移了35位 movl %ecx, %eax sarl $31, %eax #拓展被除数num的符号位,num为负数则 %eax=-1,正数则为零。此值作为结果的一个修正量。 subl %eax, %edx # %edx =%edx-%eax ,若被除数为负数,则结果减去-1(加1)。 movl %edx, %eax #最后打印结果。 movl %eax, -4(%rbp) movl -4(%rbp), %eax movl %eax, %esi movl $.LC0, %edi movl $0, %eax call printf nop
我猜测:之所以最后有个修正量,是由于实际的乘数y是一个约数,跟理论上的b值存在误差。
假设实际乘数y跟理论值b之间的误差为k(y > b,k为正数),则有:
y = b+k x*y = x*(b+k) = xb+xk
当x为正数时,实际的乘积就会比理论的大xk
当x为负数时,实际的乘积就会比理论的小xk
从上面可以看出,右移操作是向下舍入,x为正数时多出的xk会因为向下舍入而得到修正。
当x为负数时,乘积会因为向下舍入和减去的xk而比理论的值小,因此要加上1作为修正。
阅读全文
1 0
- 二进制除法转乘法原理
- 除法转乘法算法
- 二进制除法
- 二进制除法
- 二进制除法
- 二进制乘除法的实现
- 辗转相除法原理
- 负数除法与正数除法原理
- 二进制除法与模2除法的区别(转)
- 辗转相除法的原理
- 辗转相除法的原理
- 辗转相除法的原理
- 119转乘K95的幸福
- Java二进制兼容性原理
- Java二进制兼容性原理
- 二进制乘法原理
- Java二进制兼容性原理
- Java二进制兼容性原理
- Git && SVN
- opencv 利用仿射变换函数对图像进行任意角度旋转
- 加载动态效果(8点圆形转)-4
- 进入子shell的各种情况分析
- java面试题之初
- 二进制除法转乘法原理
- Java值传递和引用传递基础分析
- 中国大学排名爬虫
- 清除浮动
- 【BZOJ】2006 [NOI2010]超级钢琴 ST表+堆
- Veeam backup vmware
- 【HIT1917】 Peaceful Commission
- 检验易位构词算法
- python学习笔记 文件读写