不用除法运算,如何实现A/3呢?

fengyexia 2011-09-27 10:31:45
如题,其中A为int型的?求助各位大神啊!
...全文
4837 80 打赏 收藏 转发到动态 举报
写回复
用AI写文章
80 条回复
切换为时间正序
请发表友善的回复…
发表回复
ccbchg 2013-03-18
  • 打赏
  • 举报
回复
引用 79 楼 mujiok2003 的回复:
引用 78 楼 mujiok2003 的回复:引用 77 楼 ccbchg 的回复:愿闻其详,编译运行结果是对的啊 原因:没有可移植性且不满足题目要求。 C/C++ code?123456789101112131415161718//vc 2010能得到正确的答案int foo(int a){ 00C71260 push ebp 00C71261 ……
受教!学习了
mujiok2003 2013-03-17
  • 打赏
  • 举报
回复
引用 78 楼 mujiok2003 的回复:
引用 77 楼 ccbchg 的回复:愿闻其详,编译运行结果是对的啊 原因:没有可移植性且不满足题目要求。 C/C++ code?123456789101112131415161718//vc 2010能得到正确的答案int foo(int a){ 00C71260 push ebp 00C71261 mov ebp,esp 0……
0xaaaaaab是(float)1.0/3的尾数。
mujiok2003 2013-03-17
  • 打赏
  • 举报
回复
引用 77 楼 ccbchg 的回复:
愿闻其详,编译运行结果是对的啊
原因:没有可移植性且不满足题目要求。

//vc 2010能得到正确的答案
int foo(int a)
{ 
00C71260  push        ebp  
00C71261  mov         ebp,esp  
00C71263  sub         esp,44h  
00C71266  push        ebx  
00C71267  push        esi  
00C71268  push        edi  
   int d = (char(*)[3])a-(char(*)[3])0;
00C71269  mov         eax,dword ptr [a]  
00C7126C  cdq  
00C7126D  mov         ecx,3  
00C71272  idiv        eax,ecx  //这就是除法
00C71274  mov         dword ptr [d],eax  
   return d;
00C71277  mov         eax,dword ptr [d]  
}

//g++用了乘法,结果不正确
[code=c]
(gdb) set disassembly-flavor intel
(gdb) disassemble /m foo
Dump of assembler code for function foo(int):
3       {
   0x080483dc <+0>:     push   ebp
   0x080483dd <+1>:     mov    ebp,esp
   0x080483df <+3>:     sub    esp,0x10

4         int d = ((char(*)[3])a - (char(*)[3])0);
   0x080483e2 <+6>:     mov    eax,DWORD PTR [ebp+0x8]
   0x080483e5 <+9>:     imul   eax,eax,0xaaaaaaab //这里用了乘法,还没有问什么乘以0xaaaaaaab
   0x080483eb <+15>:    mov    DWORD PTR [ebp-0x4],eax

5         return d;
   0x080483ee <+18>:    mov    eax,DWORD PTR [ebp-0x4]

6       }
   0x080483f1 <+21>:    leave
   0x080483f2 <+22>:    ret
[/code]
ccbchg 2013-03-17
  • 打赏
  • 举报
回复
引用 76 楼 mujiok2003 的回复:
引用 75 楼 ccbchg 的回复:引用 69 楼 mujiok2003 的回复:引用 61 楼 ccbchg 的回复:(char(*)[3])A - (char(*)[3])0 很不错。处理一下为负数就更好了 我居然写了这么个答案。。。我敢说当时我肯定也是抄过来的。。害我刚刚看了半天才搞明白为什么 不过我试了一下,惊奇的发现,这个式子也能处理负数啊 ……
愿闻其详,编译运行结果是对的啊
mujiok2003 2013-03-16
  • 打赏
  • 举报
回复
引用 75 楼 ccbchg 的回复:
引用 69 楼 mujiok2003 的回复:引用 61 楼 ccbchg 的回复:(char(*)[3])A - (char(*)[3])0 很不错。处理一下为负数就更好了 我居然写了这么个答案。。。我敢说当时我肯定也是抄过来的。。害我刚刚看了半天才搞明白为什么 不过我试了一下,惊奇的发现,这个式子也能处理负数啊
这种做法是错的, 不要研究了。
ccbchg 2013-03-15
  • 打赏
  • 举报
回复
引用 69 楼 mujiok2003 的回复:
引用 61 楼 ccbchg 的回复:(char(*)[3])A - (char(*)[3])0 很不错。处理一下为负数就更好了
我居然写了这么个答案。。。我敢说当时我肯定也是抄过来的。。害我刚刚看了半天才搞明白为什么 不过我试了一下,惊奇的发现,这个式子也能处理负数啊
mujiok2003 2013-03-13
  • 打赏
  • 举报
回复
引用 61 楼 ccbchg 的回复:
(char(*)[3])A - (char(*)[3])0
很不错。处理一下为负数就更好了
bigsnowstorm 2013-03-13
  • 打赏
  • 举报
回复
//用函数实现除法,不能用除号,divider:除数,dividend:被除数, quotient:商 //如求5/2,则先得到整数商2,再由5/2的余数1:1*100000/2*0.00001得到商的小数部分 //得到商的整数部分 int divide_get_integer(int divider, int dividend) { int sum_divider=divider; int integer_result=0; while(sum_divider<=dividend) { sum_divider = sum_divider + divider; integer_result++; } return integer_result; } //得到商的小数部分 float divide_get_decimal(int divider, int dividend) { float decimal_result; //length为精度 int length=5; //cout << "please input the degree of accuracy" <<endl; //cin >>length; //商的小数部分,即dividend和divider的余数再除以除数 dividend= dividend%divider; //得到倍数 int multiple_of_10=10; float multiple_of_0_decimal_1=0.1; for(int i=0;i<length;i++) { multiple_of_10 = multiple_of_10 * 10; multiple_of_0_decimal_1 = multiple_of_0_decimal_1 * 0.1; } dividend = dividend * multiple_of_10; decimal_result = divide_get_integer(divider, dividend)*multiple_of_0_decimal_1; return decimal_result; } //得到商 float divide(int divider, int dividend) { return divide_get_integer(divider,dividend)+divide_get_decimal(divider, dividend); }
mymtom 2013-03-13
  • 打赏
  • 举报
回复
引用 72 楼 FancyMouse 的回复:
这证明哪有这么繁琐。只需要注意到0xaaaaaaab是3在mod 2^32下的乘法逆元,并且0xaaaaaaab*3 = 2*2^32 + 1。所以如果x=3*q+r的话,x*0xaaaaaaab=(3q+r)*0xaaaaaaab = 2*2^32*q + r*0xaaaaaaab r*0xaaaaaaab至多只到2*0xaaaaaaab,所以取x*0xaaaaaaab然后>>33就能提取出q。
学习了!
FancyMouse 2013-03-13
  • 打赏
  • 举报
回复
引用 39 楼 mingliang1212 的回复:
引用 37 楼 lvjing_csdn 的回复:可以解释下,为什么要左移32位,以及最后要加4吗?谢谢你 先看推导出的公式: 因为 1/3 = 1/4 + 1/4^2 + 1/4^3 + 1/4^4 ... = (1/4)(1 - (1/4)^n)/(1 - 1/4);//1 所以 A/3 = A/4 + A/16 + A/64... //2 换成乘法: A……
这证明哪有这么繁琐。只需要注意到0xaaaaaaab是3在mod 2^32下的乘法逆元,并且0xaaaaaaab*3 = 2*2^32 + 1。所以如果x=3*q+r的话,x*0xaaaaaaab=(3q+r)*0xaaaaaaab = 2*2^32*q + r*0xaaaaaaab r*0xaaaaaaab至多只到2*0xaaaaaaab,所以取x*0xaaaaaaab然后>>33就能提取出q。
大智_Unity玩家 2013-03-13
  • 打赏
  • 举报
回复
做过这道面试题 不用除法实现A/3 答案: unsigned divby3( unsigned x ) { return ((unsigned long long)x * 0xaaaaaaab) >> 33; }
lin5161678 2013-03-13
  • 打赏
  • 举报
回复
引用 58 楼 cwjcsu 的回复:
搞这些东西有意义吗
看不懂就关掉网页 少说一句 搞这东西 哪怕是开阔思路也有意义
lin5161678 2013-03-13
  • 打赏
  • 举报
回复
引用 63 楼 dwedd 的回复:
我去。。。各位高手贴方法时请给个复杂度啊,,看着真闹心啊~ 整数的除法:我应该会用二分查找。复杂度:O(log(被除数)) 如 A/3, 商肯定是在0到A中间,所以每次把中间值*3和A对比一下。小了就在右半部找,大了就在左半部。 最后找到~~ok了~ 很快哦~~
说到复杂度 他们大部分是在最追求O(1)
oKing0325 2012-10-22
  • 打赏
  • 举报
回复
不知道这个是不是超过了15个字才有经验~!
z6482 2012-10-22
  • 打赏
  • 举报
回复
A>>1之后A还是原来的值。代码如下:

int divBy3(int a)
{
int neg=a<0?-1:1;
int ret=0;
a=a<0?-a:a;
while(a!=0)
{
a=a>>1;
ret+=a;
a=a>>1;
ret-=a;
}
return neg>1?ret:-ret;
z6482 2012-10-22
  • 打赏
  • 举报
回复
昨天笔试遇到这个题目:没做出来,今天来搜索,得到了启发,我给出一个自认为最舒服的结果:
设X=A/3;那么A=X+2*X;变成移位运算A=X+X<<1;
左移会使数据越变越大,最后溢出,而右移则不然,对于32为int型向右移动32次就可以结束了,于是将上面等式左右两边同时右移一位得到:A>>1=X>>1+X;因此,
X=A>>1-X>>1;
于是有
X>>1=A>>2-X>>2;
X>>2=A>>3-X>>3;
……
X>>31=A>>32-X>>32;
得到结果:X=A>>1-A>>2+A>>3-A>>4+……+A>>31-X>>32;X>>32=0;
所以,X=A>>1+A>>3+……+A>>31-A>>2-A>>4-……-A>>3O;
于是计算X的代码可以简单表示为:
for(int i=0;i<16;i++)
{
X+=(A>>1);
X-=(A>>1);
}
记不清A>>1之后A是否会变为移位后的结果了,如果A>>1之后A还是原来的值,则应该是:
for(int i=0;i<16;i++)
{
X+=(A>>(2*i+1));
X-=(A>>(2*i+2));//2*i也可以用i<<1代替额。
}
liangbch 2011-11-15
  • 打赏
  • 举报
回复
[Quote=引用 63 楼 dwedd 的回复:]
我去。。。各位高手贴方法时请给个复杂度啊,,看着真闹心啊~

整数的除法:我应该会用二分查找。复杂度:O(log(被除数))
如 A/3, 商肯定是在0到A中间,所以每次把中间值*3和A对比一下。小了就在右半部找,大了就在左半部。
最后找到~~ok了~

很快哦~~
[/Quote]
11#,25#,30# 使用以除代乘法,复杂度是一个常数c,比 "O(log(被除数))"快多了。
dwedd 2011-11-13
  • 打赏
  • 举报
回复
我去。。。各位高手贴方法时请给个复杂度啊,,看着真闹心啊~

整数的除法:我应该会用二分查找。复杂度:O(log(被除数))
如 A/3, 商肯定是在0到A中间,所以每次把中间值*3和A对比一下。小了就在右半部找,大了就在左半部。
最后找到~~ok了~

很快哦~~
Song9007206710328 2011-10-28
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 mingliang1212 的回复:]
给个重量级的答案吧:

因为 1/3 = 1/4 + 1/4^2 + 1/4^3 + 1/4^4 ... = (1/4)(1 - (1/4)^n)/(1 - 1/4);
所以 A/3 = A/4 + A/16 + A/64...
换成乘法: A/3 = (A*4^(32-1) + A*4^(32 - 2) + A*4^(32 - 3) +... + A*4^0)/4^32;
程序如下:
……
[/Quote]
连泰勒公式都用上了,你高数看来学得很好啊!!哈哈
ccbchg 2011-10-26
  • 打赏
  • 举报
回复
(char(*)[3])A - (char(*)[3])0
加载更多回复(59)

64,685

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧