编译器将除变成乘法原理

由于除法运算效率低于乘法,编译器会在可能的情况下将除法转换为乘法。当被除数是常量时,通过移位运算可以实现这一优化。例如,a/b(b为常量)可以转换为a * k >> n,其中k和n是根据b计算出来的。然而,在负数除法中,由于计算机使用补码表示负数,这种优化可能导致错误。问题在于从原码右移后需要转换为补码,但计算机内部直接处理补码,这可能导致额外的一次位移,从而产生错误的结果。解决这个问题的关键在于正确处理负数的补码表示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

除法运算运算效率在四种基本运算中最慢,是乘法的20倍左右

所以在被除数为固定值时(重要),编译器会把除法优化乘法。

 

设代码 a/b = c                          b是常量

设 b*k = 2^n                             2的n次直接用移位运算即可

a *2^n/ (b*2 ^n) = c

a * b *k/b = c* 2^n 

a *k >> n =  c

所以 a *k >> n = a/b                  //编译器会选择n的长度 从而保证后面位数舍弃时,造成的影响最小

让我们来看一下代码                 //mul 寄存器(32位) = EDX (高位)  EAX(低位)

a * 0x38E38E39 >> 33 = a / 9

b *k = 0x38E38E39 * 9 = 0x2 0000 0001= (2^33) +1            //这个值要大于2^33 所以求值时 2^n / b 要向上取整

直接取edx相当于 >>32 然后再sar edx,1

a如果是正数则无事发生

a如果是负数呢                //例如-0x10      -16

在内存中以补码存放 即 0xFFFFFFF0           //乘法加位移后

//imul 可能是用了补码乘法,或者用原码乘法//建议用原码乘法理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值