不用加减乘除符号实现四则运算(整数)--JAVA

这种面试题...能想到的就是用位运算代替

在讲解之前,首先普及一点知识
与运算(全一才是一):
0 & 0 = 0
1 & 0 = 0
0 & 1 = 0
1 & 1 = 1
或运算(有一就是一):
0 | 0 = 0
1 | 0 = 1
0 | 1 = 1
1 | 1 = 1
非运算(就是唱反调):
~1 = 0
~0 = 1
异或运算(不同才是一):
0 | 0 = 0
1 | 0 = 1
0 | 1 = 1
1 | 1 = 0
移位运算:
左移末尾自动补0
000010 << 1 = 000100
右移,含符号,首部补符号位
1110110 >> 1 = 11110111
右移,无符号,首部自动补零
1110110 >>> 1 = 01111011

好了,普及就到这了,接着往下看吧
-----------------------可爱的分割线---------------------------------
加法:
因为位运算都是针对二进制的,我们不太好理解,那我们看一下十进制的时候咱是怎么算的:
12+19 = 31
首先,从末尾开始相加,加完后溢出的部分放到前面与下一位相加,这是幼儿园的做法;
那我们换个思路,首先不考虑进位,首先逐位相加,得到的结果与进位结果相加,不断迭代直到没有进位;
那上面那个题
12+19,逐位相加,
得到21,进位10,逐位相加,
31,进位0,得到结果。

其实二进制也是一样的,加法问题就转化成了:
1.获取逐位相加的结果
2.获取进位的值
不断将这两个结果在此相加,直到没有进位,那不就是最终的结果了嘛(笑)

单个位的加法规则:
0 + 0 = 0 (进位 0)
1 + 0 = 1 (进位 0)
0 + 1 = 1 (进位 0)
1 + 1 = 0 (进位 1)
发现没,逐位加法和异或操作结果一样,获取进位和与操作后左移一位结果一样;
解决了,代码如下:
public int add(int a, int b){
while(b != 0){
int sum = a ^ b;
int pos = (a & b) << 1;
a = sum;
b = pos;
}
return a;
}
-----------------------可爱的分割线---------------------------------
减法:
emmmmmmmmmmmm,起初我还想了很久,后来真是被自己蠢到了
a - b 不就是 a + (-b) 么......
那问题就变成了怎么用位运算取到 -b
这个..就很简单了 -n = ~n+1
代码如下:
public int minus(int a,int b) {
return add(a, ~b+1) ;
}
对了,我们不是不让用加减乘除符号嘛,好好好,我改...
public int minus(int a,int b) {
return add(a, add(~b, 1));
}
-----------------------可爱的分割线---------------------------------
乘法:
符号问题的话,不考虑,全按整数算,大不了最后取反就是了。
最简单的,乘法不就是多个加法嘛,
对,引用我高中数学老师的话,我不能说你错,但你这也不对
因为太--------慢--------了--------
我们的算法最差也会在32次循环内结束,如果累加的话,就会导致计算规模随b绝对值的增大而增大,这不是我们希望看到的。
还是那个思路,正常十进制是怎么算的
12*56,首先个位相乘,十位相乘后乘十,百位乘十后乘百....最后结果相加
沿着这个思路,到了二进制反而简单了,为什么呢
首先,乘数只有0和1啊,即全清空和全保留,好像.. 啥也不用做诶
乘十,到了这里就变成了乘2,那....左移就可以了
至于结果累加.....我们上面不是做过了嘛~
看代码吧:
public int multi(int a, int b){
int ans = 0;
int index = 0;
while(b != 0){
if( (b&1) == 1){// 判断最后一位是不是1
ans = add(ans, a << index);
}
index = add(index, 1);
b = b >> 1;
}
return ans;
}
-----------------------可爱的分割线---------------------------------
emmmmmmmmmmmm,我早就想吐槽楼上了,一点都不可爱好吗!
呼,终于到最后一个了,还是最简单的思路,反复的减去除数直至被除数小于除数就行了
但又回到了问题规模的问题,如果被除数过大,除数过小,就会出现循环次数过多的问题
这次我们就用乘法的逆运算,先找结果中第一个一的位置,即满足被除数>=除数<<x中x的最大值
然后相减,即贪心算法
代码如下:
public int divide(int a, int b) {
int flag = 1;
// 处理符号问题
if(a >> 31 == 1){
a = add(~a, 1);
flg = add(~flg, 1);
}
if(b >> 31 == 1){
b = add(~b, 1);
flg = add(~flg, 1);
}

    int re = 0;  
    while (a >= b){  
        int aa = 1, temp = b;  
        while (temp < (a>>1)){  
            temp <<= 1;  
            aa <<= 1;  
        }  
        a -= temp;  
        re += aa;  
    }  
    return re*flag;  
}

-----------------------可爱的分割线---------------------------------
(我丢~楼上砍你哦!)
总结,
上面的操作有一些位运算的技巧在这里说一下:
b & 1 :取一个数的最后一位
~n+1 :对n取反
-n &n :整数二进制串中最后一个1
n&(n-1) :去掉整数二进制串中最后一个1
n ^ n = 0
其实,这篇文章还是不太专业的,比如,举例时用的都是整数,细心的同学可能发现我没有加判定条件,那负数为什么也适用呢?这就涉及到计算机编码的知识了,其实就是补码和反码,有兴趣的同学合一自行百度;

还有就是没有考虑到整数溢出的问题,int型变量的取值范围是[-2^31, 2^31-1],对于
(2^31-1)+1这样的操作是会造成溢出的,但如何处理不在我们今天的讨论范围,有兴趣的同学可以自行百度
好啦,就这么多吧,这里只是一个位运算的引子,其实计算机还是蛮有趣的,共勉。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,784评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,745评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,702评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,229评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,245评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,376评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,798评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,471评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,655评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,485评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,535评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,235评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,793评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,863评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,096评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,654评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,233评论 2 341

推荐阅读更多精彩内容

  • 8086汇编 本笔记是笔者观看小甲鱼老师(鱼C论坛)《零基础入门学习汇编语言》系列视频的笔记,在此感谢他和像他一样...
    Gibbs基阅读 37,094评论 8 114
  • 我们知道,计算机最基本的操作单元是字节(byte),一个字节由8个位(bit)组成,一个位只能存储一个0或1,其实...
    JxYoung阅读 41,044评论 22 90
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,547评论 18 399
  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...
    小白兔去钓鱼阅读 8,966评论 0 13
  • 【书名】《拆掉思维里的墙》 【作者】古典 【金句】 001沉没成本其实是已经损失的成本,为了这个损失而追加成本,最...
    李潇潇me阅读 215评论 0 0