加减乘除求余 利用 位运算实现(详细)
这几天培训,偶然看到这样一道题目:
用位运算实现除法和求余运算?这一下子把不了解二进制的小白搞蒙了。
因此,查阅许多资料,写出用位运算实现的加减乘除以及求余的代码,附详细思路,权当笔记,也分享给大家。
首先,我们得了解位运算符:
符号 |
描述 |
运算规则 |
& |
与 |
两个位都为1时,结果才为1 |
| |
或 |
两个位都为0时,结果才为0 |
^ |
异或 |
两个位相同为0,相异为1 |
~ |
取反 |
0变1,1变0 |
<< |
左移 |
各二进位全部左移若干位,高位丢弃,低位补0 |
>> |
右移 |
各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移) |
(1) 首先是&,按位与运算符,两个位都为1时,结果才为1。
例:
2 & 3 ==> 0000 0010 & 0000 0011 = 0000 0010 即2 & 3 = 2
可见,对于十进制转换成的二进制数,按照相应位的比对而得出结果。
(2)其次是 | ,按位或运算符,两个位都为0时,结果才为0,
例:
2 & 3 ==> 0000 0010 | 0000 0011 = 0000 0011 即2 | 3 = 3
(3)按位异或运算符^,两个位相同为0,相异为1。
例:
2 ^ 3 ==> 0000 0010 ^ 0000 0011 = 0000 0001 即2 ^ 3 = 1
(4)取反~,很好理解,0变1,1变成0.
例:
~3 即 0000 0011 ==> 1111 1100
(5)最后,按位左移 和 按位右移 的意思就是字面意思。
例:
3<<1 即 0000 0011 ==> 0000 0110
3<<2 即 0000 0011 ==> 0000 1100
好了,基础知识到位,开始理论研究!
加法
我们先从加法开始,先看一个二进制加法图:
研究1+1 可以看出,最低位满2进1,即1 和 1 => 0 (1^1=0)
然后前进一位加上1,即 0 和 0 => 1 (应由前一位的1&1=1来获得进位数,此时按位左移即进位)
研究2+1 可以看出,因为不需要进位,即 0 和 1 => 1
研究3+1 运用研究1+1 和 2+1的结论,可以发现只是前两者的嵌套。
因此,我们发现,1 和 1 的运算 ,同位变成0,上一位由0变1,或由1变0
,以1+1为例,得到:
最后,代码实现:
int Add(int a,int b)//加法位运算a+b
{if(b){return Add(a ^ b, (a & b) << 1);}else{return a;}
}
减法
很容易想到,减法就是加上一个数的负数
而二进制负数如何得来?这里转载一些资料:
在二进制里,最高位为符号位,用0和1 来表示正负,最高位为 1 代表负数,最高位为 0 代表正数。
负数的二进制表示分为三步:
1 把这个负数的绝对值转换为二进制,即求原码
2 把原码取反,即求反码
3 把反码加1,即求补码
例如把 -5 转换为二进制,假设-5为Java中的byte类型。
bytei=5;
1 求原码:即把-5的绝对值5转换为二进制 为 00000101
2 求反码:为 11111010
3 求补码:为 11111011
来自 <计算机基础知识 | 负数的二进制表示 - 知乎>
因此,代码只需要将减数求反以及补码即可
int Subt(int a, int b)//减法位运算a-b
{return Add(a, Add(~b, 1));
}
乘法
按照小学的理解,其实就是被乘数进行乘数次的累加而已:
如:3*3 就是3+3+3
代码实现:
int Multi(int a, int b)//乘法位运算a*b
{int i,sum=0;for (i=b;i>0;i--){sum=Add(sum,a);}return sum;
}
后面转载乘法的另一种思路:
一开始考虑到乘法其实是加法的延续,是一种累加运算,只要将被乘数进行乘数次相加即可,但这样的做法存在一个很明显的问题即当乘数很大时需要进行多次加法运算。下面介绍一种改进的乘法思路,这种思路由手作乘法的过程的方法而来。在进行手动乘法时,我们根据乘数的尾数是否为1来确定是否需要相加。即若乘数的尾数是1,那么就要加上被乘数,否则则不需要加上被乘数。在本次判断之后,我们需要将被乘数左移一位,乘数逻辑右移一位。整个过程在乘数为0时停止。
同时需要注意符号的问题,这里我们首先进行绝对值的运算,再通过a^b是否小于0判断符号的异同性。
int Multiply(int a, int b){int a1 = a > 0 ? a : Add(~a, 1);int b1 = b > 0 ? b : Add(~b, 1);int sum = 0;while(b1){if(b1 & 0x1){sum = Add(sum, a1);}a1 = a1 << 1;b1 = b1 >> 1;}if((a ^ b) < 0)return Add(~sum, 1);else return sum;
}
转自 位运算实现加减乘除运算——超详细C语言描述_Pe_99y的博客-CSDN博客
除法
除法同理,即是乘法的逆运算,重复减除数,知道被除数小于除数
代码实现:
int Divide(int a,int b)
{int i=0;while(a<b){subt(a,b);i++;}return i;
}
下面再转载另一种思路的文章:
跟加法、减法一样,除法是乘法的逆运算,那么除法就是做有限次的减法,直到被减数小于减数为止。这种思路类似于乘法中的简单思路,问题同样是在被除数远大于除数时,需要做多次除法。
改良的除法思路如下,考虑到int型整数占32位,那么用i = 31开始比较被除数与除数的2i的大小,若被除数大,则在商处直接加上i从而减小减法的次数。
int Divide(int a, int b){ int quotient = 0;if(!b){cout << "Error" << endl;return 1;}for(int i = 31; i --; i > 0){if((a >> i) >= b){quotient = Add(quotient, 1 << i);a = Minus(a, b << i);}}if((a ^ b) < 0)quotient = Add(~quotient, 1);return quotient;
}
原文链接:https://blog.csdn.net/qq_41716838/article/details/92193515
求余
求余即是用除法的结果乘上原除数,与被除数做差
代码实现:
int fish(int a,int b)//求余位运算a%b
{int c,f;c = Divide(a,b);f = a - (Multiply(b,c));return f;
}
最后,我们可以进行5种运算,做开始那道题更是毫无压力。
本文除了引用(以附原链接)均原创,谢谢大家支持和学习!
加减乘除求余 利用 位运算实现(详细)相关推荐
- java大整数的加减乘除_关于大整数的加减乘除求余运算 java
自己用java 实现了大字符串整数的加减乘除和求余运算, 加减法的算法是模拟手工笔算的计算过程, 除法就是从最高位不停的减操作, 乘法的算法 :遍历一个数的各个位数以及他所在位置,另一个数根据这个数的 ...
- php 位运算与权限,PHP巧妙利用位运算实现网站权限管理的方法
首先我们先定义4个常量来设定四种权限: ===================================== define(ADD,1);//增加数据库记录的权限 define(UPD,2);/ ...
- 利用位运算和指针实现的交换两个数的程序
位运算是C语言的一大特色,利用异或运算可以实现交换两个数,原理是一个整数与另外一个数进行两次异或运算仍然是其本身,基本原理用式子表达如下: (1) A ^ A = 0; (2) A = A ^B; ( ...
- 利用位运算解决 N 皇后问题
题目: LeetCode 51. N-Queens 分析: N 皇后问题是考查递归回溯的经典问题,深度优先搜索的难点在于如何剪枝,在这个问题里面的剪枝,我们需要利用额外的空间去记录当前行的有效空位,只 ...
- C# 利用位运算传递多个参数方法
前言 在工作中用sendMessage的方法向另外一个进程中传递窗体的位置,长度,宽度四个值,但是sendMessage的方法签名中只有两个参数.于是在网上找到了一些代码,找到了这个利用位运算来合并参 ...
- php取模,PHP的求余(取模)运算
这篇文章主要介绍了关于PHP的求余(取模)运算 ,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 先来看下个小案例:$n = 8.45; $result = $n*100; echo g ...
- 利用位运算控制开关灯问题
<C++笔记> 利用位运算控制开关灯问题 新手上路,可能有很多不足的地方,欢迎大家多多在留言区提出自己的观点以及更好的办法. 问题描述:俱乐部一共有32盏灯,设计一个灯光控制系统,共有4部 ...
- php 求余 负数,PHP的求余(取模)运算
这篇文章主要介绍了关于PHP的求余(取模)运算 ,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 先来看下个小案例:$n = 8.45; $result = $n*100; echo g ...
- C++实现大数运算(加减乘除求余)
前言: 只有部分GCC编译器支持int128,而我们平常使用的软件,最大只有_int64.当这些不够用时,我们该怎么办? 我本身想写代码实现整数型大数据的加减乘除和求余,结果写着写着想着连小数运算的也 ...
- 剑指 Offer 65. 不用加减乘除做加法(位运算、递归、迭代)
一.题目 剑指 Offer 65. 不用加减乘除做加法 题目描述 写一个函数,求两个整数之和,要求在函数体内不得使用 "+"."-"."*" ...
最新文章
- On-Heap与Off-Heap
- centos中查找某一段时间的文件
- ASP 三十二条精华代码
- ubuntu之路——day8.4 Adam自适应矩估计算法
- 齐博地方门户系统v5_社区团购小程序哪个好?-小猪V5社区团购系统,社区团购系统,社区团购小程序,专注社区团购系统研发...
- 【机器学习】为什么GBDT可以超越深度学习
- Spring Boot——控制台LOGO自定义配置管理解决方案
- php获取ios,IOS 通过描述获取UDID PHP代码版
- 解决修改sources.list之后update NO_PUBKEY错误
- mysql rs.next_JDBC结果集rs.next()注意事项
- 【C/C++】一道试题,深入理解数组和指针
- 第九课 如何调试以太坊官网的智能合约众筹案例
- 小知识·OTG工作原理
- 用计算机能算重量加权平均长度吗,利用计算器求平均数检测试题与*
- 怎么知道是否已经被好友删了微信?
- python爬虫餐饮行业数据分析统计服_Python数据分析实战,简单快速制作餐饮行业商业化报告...
- 【零信任落地案例】启明星辰中国移动某公司远程办公安全接入方案
- 微信小程序——弹出并隐藏键盘(带有输入框,可编辑)
- 深扒中国最神秘的百亿快时尚巨头SheIn
- android流水App(记账本)--数据库实现多功能