java todo fixme_TODO-FIXME:在Java 8的Integer类中?

52429是与(2 ^ 19)/ 10最接近的整数,因此除以10可以通过乘以52429,然后除以2 ^ 19来实现,其中后者是平凡的位移操作而不是需要完全除法.

根据这个(C语言)片段,代码作者似乎建议使用shift / add操作来更加优化地进行乘法:

uint32_t div10(uint16_t in)

{

// divides by multiplying by 52429 / (2 ^ 16)

// 52429 = 0xcccd

uint32_t x = in << 2; // multiply by 4 : total = 0x0004

x += (x << 1); // multiply by 3 : total = 0x000c

x += (x << 4); // multiply by 17 : total = 0x00cc

x += (x << 8); // multiply by 257 : total = 0xcccc

x += in; // one more makes : total = 0xcccd

return x >> 19;

}

我无法回答的是为什么他们显然认为这可能比Java环境中的直接乘法更优.

在机器代码级别,只有在没有硬件乘法器的(现在很少见的)CPU上,最简单的(尽管可能是天真的)乘法函数需要16个移位/加法运算来乘以两个16位数字才能更加优化.

另一方面,像上面这样的手工制作的函数可以通过利用该常量的数字属性以较少的步长执行乘法,在这种情况下将其减少到四个移位/添加操作而不是16.

FWIW(有点令人印象深刻)macOS上的clang编译器,即使只有-O1优化标志实际上将上面的代码转换回单个乘法:

_div10: ## @div10

pushq %rbp

movq %rsp, %rbp

imull $52429, %edi, %eax ## imm = 0xCCCD

shrl $19, %eax

popq %rbp

retq

它也转向:

uint32_t div10(uint16_t in) {

return in / 10;

}

完全相同的汇编代码,这只是表明现代编译器确实最了解.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值