首先介绍计算机的二进制码

二进制常用的有原码,反码和补码,他们都是由最左边的一个符号位和右边的数值位构成。在计算机中为了更低成本的计算,数据都是用补码来存储和运算的。

原码

最高位表示符号位(0代表正数,1代表负数)。剩下的位数,是这个数的绝对值的二进制。

比如 一个int变量大小为4字节,在32位的编译器中的二进制表示就是00000000 00000000 00000000 00000000
那么10 的原码就是00000000 00000000 00000000 00001010
−10的原码就是 10000000 00000000 00000000 00001010

反码

正数的反码和其原码是一样的
负数的反码就是在其原码的基础上 符号位不变 其他位取反。

10的反码就是00000000 00000000 00000000 00001010 和原码一样
−10的反码就是11111111 11111111 11111111 11110101

补码

正数的补码就是其原码
负数的补码就是在其反码的基础上+1

10的补码就是00000000 00000000 00000000 00001010
−10的补码就是 11111111 11111111 11111111 11111011

总结一下

计算机系统中,数值一律用补码来表示:因为补码可以使符号位和数值位统一处理,同时可以使减法按照加法来处理。
二进制编码:数值编码分为原码,反码,补码,符号位均为0正1负。

原码 -> 补码: 数值位取反加1

补码 -> 原码: 对该补码的数值位继续 取反加1

补码 的绝对值(称为真值):正数的真值就是本身,负数的真值是各位(包括符号位)取反加1(即变成原码并把符号位取反).

介绍基本的位操作

^:按位异或;&:按位与; | :按位或
b -> -b : 各位(包括符号位)取反加1

用位操作实现加法运算

我们先不考虑进位,在1位数的加法上,如下
1. 1+1=0
2. 1+0=1
3. 0+1=1
4. 0+0=0
很明显上面几个表达式我们可以用异或进行统一
1. 1^1=0
2. 1^0=1
3. 0^1=1
4. 0^0=0
这样我们就完成了最基础的一位数的加法,但是怎么计算二位以上的加法呢?我们发现现在方法的问题在于不能够获取进位,于是我们通过观察一位数的加法的式子,发现只有两个数位都是1的时候才会有进位,其他都不进位,这不是和&很像吗? 我们通过把+换成&得到下式
1. 1&1=0 不进位
2. 1&0=1 不进位
3. 0&1=1 不进位
4. 0&0=0 进位
那么我们把所有位进行&操作,然后<<左移一位,不就可以当作加数当前的进位吗?
到这里我们就完整解决了二进制相加问题中,对应位的相加和进位的问题
1. x^y 加法
2. (x&y)<<1 进位操作
那么总结一下:

定理1:设a,b为两个二进制数,则a+b=a^b+(a&b)<<1。
证明:

a^b是不考虑进位时加法结果。当二进制位同时为1时,才有进位,因此 (a&b)<<1是进位产生的值,称为进位补偿。将两者相加便是完整加法结果。

定理2:使用定理1可以实现只用位运算进行加法运算。
证明:

利用定理1中的等式不停对自身进行迭代。每迭代一次,进位补偿右边就多一位0,因此最多需要加数二进制位长度次迭代,进位补偿就变为0,这时运算结束。

那么我们可以根据上面的定理得到实际的C++代码如下

int add(int a, int b){int re = a;while(b){int tmp = a;a = a^b;b = (tmp&b)<<1;re = a;}return re;
}

用位操作实现减法

减法和加法原理相同,减去一个数相当于加上这个数的相反数,所以完全可以利用加法操作,唯一需要做的就是求出被减数的相反数。
求相反数的方法:每一位取反,末位加一。
代码如下:

int subtraction(int a, int b)
{b = add(~b,1); // 求b的相反数return add(a, b);
}

用位操作实现乘法

二进制的乘法同十进制的乘法并无什么不一样,对于a∗b每次只需要将a左移对应的位,然后同上一次的结果相加即可
当b的对应位为1的时候,对a左移一位相加即可
当b的对应位位0的时候,对a左移一位,但是不相加
注意到我们上面的操作都是不包括符号位的,因此我们单独考虑符号位。
代码如下

int getSign(int n)
{unsigned count = 0;//计算n的位数do{++count;}while(n >> count)//得到n的最左边的位return n >> (count-1);
}int mul(int a, int b){bool isNegative = false;if(getSign(a) ^ getSigned(b))isNegative = true;if(a < 0) a = add(~a,1);//求出a的绝对值if(b < 0) b = add(~b,1);//求出b的绝对值int res = 0;while(b){               //当b不为0,继续循环if(b & 1)           //当b当前位为1 才需要加ares = add(res,a);a = a << 1;b = b >> 1;}if(isNegative)add(~res,1);return res;
}

二进制除法

同乘法一样,除法一样可以用减法来代替,当a≥b才可以上商,在每次上一个商(也就是商值加1)之后,a=a−b
代码如下

int divide(int a, int b){if(!b)throw std::runtime_error("Divided can't be zero...");bool isNegative = false;bool isNegtive = false;if(getSign(a) ^ getSign(b))isNegtive = true;if(a < 0) a = add(~a,1);//求出a的绝对值if(b < 0) b = add(~b,1);//求出b的绝对值int res = 0;while(a >= b){res = add(res,1);a = subtraction(a,b);}if(isNegative)add(~res,1);return res;
}

---------------------
作者:harry_128
来源:CSDN
原文:https://blog.csdn.net/harry_128/article/details/80150502
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

[转]C++二进制完成加减乘除相关推荐

  1. Java二进制的加减乘除

    引子 某天研究 fail-fast机制的时候,去看了看hashCode的实现方式,然后发现每个对象的实现都不一样:于是研究一个String的:于是看到公式: s[0]*31^(n-1) + s[1]* ...

  2. 二进制与加减乘除的物理层实现

    一,二进制0,1的实现 https://www.zhihu.com/question/20112194 二.加减乘除的实现 从数学上将,CPU中的ALU在算术上只干了两件事,加法,移位,顶多加上取反, ...

  3. 二进制的加减乘除法全了看一下叭

    看这里~ 前言 一.二进制加法 二.二进制减法 三.二进制乘法 四.二进制除法 总结 前言 最近在学习通信网络中的CRC算法,所以积累一下二进制的各种算法,如果对您有用,记得点个赞喔!谢谢啦. 一.二 ...

  4. C++二进制完成加减乘除

    首先介绍计算机的二进制码 二进制常用的有原码,反码和补码,他们都是由最左边的一个符号位和右边的数值位构成.在计算机中为了更低成本的计算,数据都是用补码来存储和运算的. 原码 最高位表示符号位(0代表正 ...

  5. -32767转化为二进制_程序员需要了解的硬核知识之二进制

    我们都知道,计算机的底层都是使用二进制数据进行数据流传输的,那么为什么会使用二进制表示计算机呢?或者说,什么是二进制数呢?在拓展一步,如何使用二进制进行加减乘除?二进制数如何表示负数呢?本文将一一为你 ...

  6. 计算机基础- -计算机为什么要使用二进制

    计算机基础- -计算机为什么要使用二进制 文章目录 计算机基础- -计算机为什么要使用二进制 一.为什么用二进制表示 二.什么是二进制数 三.移位运算和乘除的关系 四.便于计算机处理的补数 五.算数右 ...

  7. c语言0和1二进制,二进制0和1代表什么

    满意答案 bosimao45 2013.07.08 采纳率:49%    等级:12 已帮助:11763人 0-1=1 加法 有四种情况: 0+0=0 0+1=1 1+0=1 1+1=10 0 进位为 ...

  8. 二进制除法教程计算机基础,计算机应用基础第四章《二进制的学习》课件.ppt...

    <计算机应用基础第四章<二进制的学习>课件.ppt>由会员分享,可在线阅读,更多相关<计算机应用基础第四章<二进制的学习>课件.ppt(26页珍藏版)> ...

  9. 欧洲人发明的的计算机语言,二进制是中国人发明的,还是欧洲人发明的?

    原标题:二进制是中国人发明的,还是欧洲人发明的? 大家好,这里是小播读书,今天要带大家了解的是著名的哲学家.数学家,近代三大理性主义思想家之一:莱布尼茨. 近代西方哲学思想主要分为两派:经验主义和理性 ...

最新文章

  1. 985 博士:导师是院士,直到毕业,我们都没单独说过一句话...
  2. 软件开发行业,年轻与大龄程序员的生存现状
  3. 苹果企业证书_今日更新:丨企业证书已更新丨苹果丨安卓软件下载说明丨
  4. 垃圾邮件分类实战(SVM)
  5. python文本处理第三方库是什么_python第三方库网站
  6. spring mvc 中文乱码 post与get的方法解决
  7. php新闻模块,新闻模块的代码~!
  8. yii2 php反射,Yii2.0-advanced-3—为yii2添加后台模板adminlte和权限组件yii2-adm
  9. php 后端 轻量 框架,GitHub - 22cloud/mixphp: 轻量 PHP 框架,基于 Swoole 的常驻内存型 PHP 高性能框架 (开发文档完善)...
  10. 前端-----今日份小练习
  11. HenCoder Android 开发进阶: 自定义 View 1-1 绘制基础
  12. 手把手教你获得CSDN徽章:CSDN IT冷知识 每日一练
  13. 一维的热传导方程向前差分法
  14. 复杂电路简化经典例题_复杂电路的简化策略
  15. 1. stm32h7 移植RTX5(AC6) 基于CUBEMX
  16. #腾讯云·未来开发者云梯计划#第三期上线啦!全国5000个免费云认证培训考试名额开放报名中!
  17. 【矩阵乘】【DP】【codevs 1305】Freda的道路
  18. 学习LSSVM以及区别LSSVM和SVM看的几篇博文
  19. Hadoop基础操作--查询集群的计算资源信息
  20. iPhone 6/6Plus UI界面设计和适配尺寸规范

热门文章

  1. 基于mini2440的ov9650摄像头裸机测试
  2. poj-1980 Unit Fraction Partition **
  3. 我看ITIL在中国(六):如何建立有中国特色的IT运维管理平台【二】
  4. YARP(Yet Another Reverse Proxy)是使用 .NET 构建的高度可定制的反向代理
  5. C# 通过正则表达式来限制控件输入有效性
  6. 强制升级?!.NET Core 2.1容器镜像将从Docker Hub中删除
  7. Windows 11 操作系统最低硬件要求
  8. 技术分享|集成开放平台使用Consul Watch机制实现配置热更新
  9. Monitor 监测CPU与内存
  10. 通过Dapr实现一个简单的基于.net的微服务电商系统(二)——通讯框架讲解