机器数和机器数的真值

一个数在计算机中的二进制表示形式,叫做这个数的机器数。机器数是带符号的,在计算机用机器数的最高位存放符号,正数为0,负数为1。举个例子,比如在机器字长为8位的情况下(机器字长是指计算机直接处理的二进制数据的位数,它决定了计算机的运算精度,一般是8的整数倍,8位、16位、32位、64位、128位),十进制中的+3,转换成二进制就是0000 0011,如果是-3,转换成二进制就是1000 0011。转换的二进制数0000 0011和1000 0011就是机器数。

这里我们还需要知道的就是机器数的真值,由于机器数的第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数1000 0011,其最高位1代表负,其真正数值是-3,而不是形式值131(1000 0011转换成十进制等于131),所以,为了区别起见,将带符号的机器数对应的真正数值成为机器数的真值。比如0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1

原码、反码和补码的基础概念和计算方法

上面我们了解了机器数,也就是二进制数,不过计算机要使用一定的编码方法进行储存,原码、反码和补码就是机器存储一个具体数字的编码方式。

原码

原码就是符号位加上真值的绝对值,即用第一位表示符号,其余位表示值,比如:如果8位二进制:

[+1]原= 0000 0001

[-1]原= 1000 0001

第一位是符号位,因为第一位是符号位,所以8位二进制数的取值范围就是:(即第一位不表示值,只表示正负。)[1111 1111 , 0111 1111],也就是十进制的[-127 , 127](小声哔哔,其实可以说成原码是带符号的机器数)

反码

正数的反码就是其本身,负数的反码是其原码的基础上,符号位不变,其余各个位取反。

[+1] = [0000 0001]原= [0000 0001]反

[-1] = [1000 0001]原= [1111 1110]反

补码

补码的表示方法是,正数的补码就是其本身,负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1(也就是在其反码的基础上+1)

[+1] = [0000 0001]原= [0000 0001]反= [0000 0001]补

[-1] = [1000 0001]原= [1111 1110]反= [1111 1111]补

知道了这三个基本概念之后,值得一提的是,如果用反码相加,会产生两个零的问题(-0和+0),所以我们使用补码,不仅仅修复了0的符号以及存在两个编码的问题,而且还能够多表示一个最低数。这就是为什么8位二进制,使用原码或反码表示的范围为[-127, +127],而使用补码表示的范围为[-128, 127]。因为机器使用补码,所以对于编程中常用到的有符号的32位int类型,可以表示范围是: [-2^31, 2 ^ 31-1] 因为第一位表示的是符号位,而使用补码表示时又可以多保存一个最小值。

位运算基本操作

加法

  1. 不考虑进位的按位求和, 异或
  2. 只考虑进位,只有(1,1)才会产生进位,使用按位与可以满足要求。 当前位产生进位,要参与高一位的运算,因此按位与后要向左移动一位。
  3. 递归求和,直到进位为0
int add(int a,int b) {int carry,add;do{add = a^b;carry = (a&b)<<1;a = add;b=carry;}while(carry!=0);return add;
}

减法

我们知道了位运算实现加法运算,那减法运算就相对简单一些了。我们实现了加法运算,自然的,我们会想到把减法运算11 - 6变形为加法运算11 + (-6),即一个正数加上一个负数。是的,很聪明,其实我们的计算机也是这样操作的,那有的人会说为什么计算机不也像加法器一样实现一个减法器呢?对的,这样想当然是合理的,但是考虑到减法比加法来的复杂,实现起来比较困难。为什么呢?我们知道加法运算其实只有两个操作,加、 进位,而减法呢,减法会有借位操作,如果当前位不够减那就从高位借位来做减法,这里就会问题了,借位怎么表示呢?加法运算中,进位通过与运算并左移一位实现,而借位就真的不好表示了。所以我们自然的想到将减法运算转变成加法运算。怎么实现呢?

刚刚我们说了减法运算可转变成一个正数加上一个负数,那首先就要来看看负数在计算机中是怎么表示的。

+8在计算机中表示为二进制的1000,那-8怎么表示呢?很容易想到,可以将一个二进制位(bit)专门规定为符号位,它等于0时就表示正数,等于1时就表示负数。比如,在8位机中,规定每个字节的最高位为符号位。那么,+8就是00001000,而-8则是10001000。这只是直观的表示方法,其实计算机是通过2的补码来表示负数的,那什么是2的补码(同补码,英文是2’s complement,其实应该翻译为2的补码)呢?它是一种用二进制表示有号数的方法,也是一种将数字的正负号变号的方式,求取步骤:

第一步,每一个二进制位都取相反值,0变成1,1变成0(即反码)。

第二步,将上一步得到的值(反码)加1。

简单来说就是取反加一!先转换为加法: a-
b = a+(-b) = a+(~b+1)

int subtraction(int a,int b){return add(a,add(~b,1));
}

乘法

 //a 被乘数,b 乘数int multiplication(int a,int b){int i = 0;int res = 0;//乘数不为0while (b != 0){//处理当前位//当前位是1if ((b & 1) == 1){res += (a << i);b = b >> 1;//记录当前是第几位i++;}else {//当前位是0b = b >> 1;i++;}}return res;}

除法

考虑我们现实生活中手动求乘积的过程,这种方式同样适用于二进制,下面我以13*14为例,向大家演示如何用手动计算的方式求乘数和被乘数绝对值的乘积。

从上图的计算过程可以看出,如果乘数当前位为1,则取被乘数左移一位的结果加到最终结果中;如果当前位为0,则取0加到乘积中(加0也就是什么也不做)

(1) 判断乘数是否为0,为0跳转至步骤(4)
(2) 将乘数与1作与运算,确定末尾位为1还是为0,如果为1,则相加数为当前被乘数;如果为0,则相加数为0;将相加数加到最终结果中;
(3) 被乘数左移一位,乘数右移一位;回到步骤(1)
(4) 确定符号位,输出结果;

 //a 被乘数,b 乘数int multiplication(int a,int b){int i = 0;int res = 0;//乘数不为0while (b != 0){//处理当前位//当前位是1if ((b & 1) == 1){res += (a << i);b = b >> 1;//记录当前是第几位i++;}else {//当前位是0b = b >> 1;i++;}}return res;}

参考链接

彻底搞清楚Java的位运算(位实现加减乘除): 彻底搞清楚Java的位运算(位实现加减乘除).

Java 实现位运算计算加减乘除相关推荐

  1. java用位运算实现加减乘除

    个人主页:熬夜磕代码丶 作品专栏: java se 我变秃了,也变强了 给大家介绍一款程序员必备刷题平台--牛客网 点击注册一起刷题收获大厂offer吧 文章目录 前言 一.常见位运算 1. & ...

  2. java加减_Java位运算实现加减乘除

    一.加法 a+b 举例实现:13+9=22 13+9不考虑进位结果为12 只考虑进位结果为10 和刚好是22. 13二进制为1101,9二进制为1001. 不考虑进位结果为0100.算式为a^b 只考 ...

  3. 只使用位运算实现加减乘除

    在线OJ: LeetCode 29. 两数相除 原题目的要求是不能使用乘法, 除法和取余运算符实现除法. 在本篇博客中把题目要求提高一点, 这里只使用位运算来实现, 顺便的也就把只使用位运算实现加减乘 ...

  4. C++学习笔记-----用位运算实现加减乘除

    C++学习笔记-----用位运算实现加减乘除 原文:http://blog.csdn.net/sinat_35261315/article/details/72904945 数据在计算机内存中是以二进 ...

  5. 算法之美 | 位运算的巧妙奥秘(一) | JAVA中位运算的深入浅出

    文章目录 前言 一.位运算符号 二.位运算的运算规则 扩展 前言 传智杯初赛后有感而写,我目前阶段所学习的算法,只是最基础的数学,对于数字和数学公式还是不敏感,在小卡与质数2那道题,解题的思路只有最基 ...

  6. java的位运算的意义

    最近,由于工作原因在编写教材时,对java的位运算进行了深入了解,现记录如下.       首先要明白一个概念,Java位运算是针对于整型数据类型的二进制进行的移位操作.主要包括位与.位或.位非,有符 ...

  7. java int位运算_java中int的表示方法,位运算的解析

    随着时代的不断发展,越来越多的人开始投入到java的学习当中来.今天就来为大家介绍java中int的表示方法以及位运算的内容有哪些一起来看看吧. 首先我们需要知道的是,在java中,int是使用32位 ...

  8. 用位运算计算两数的和

    用位运算计算两数的和 文章目录 用位运算计算两数的和 方法一: 方法二: 方法一: //方法一: //sum为计算结果 //carry为进位 int bitAdd(int a, int b) {if ...

  9. 【C++】位运算实现加减乘除

    1 #include<iostream> 2 #include<assert.h> 3 using namespace std; 4 5 // 位运算实现加减乘除 6 7 in ...

最新文章

  1. LeetCode简单题之判断国际象棋棋盘中一个格子的颜色
  2. Xamarin Android提示找不到资源属性定义
  3. 32 usb 配置描述符_USB协议详解第4讲(USB描述符标准配置描述符)
  4. vue axios 配置上服务器后报错'Access-Control-Allow-Origin' header](亲测)
  5. python学习-抓取知乎图片
  6. centos7 修改为任意网卡名_VirtualBox虚拟机双网卡配置实现与本机互通并上网
  7. Amazon SQS 消息队列服务
  8. Response.End(); 用HttpContext.Current.ApplicationInstance.CompleteRequest 代替
  9. jupyter not a color scheme terminal
  10. 网站选择按钮点击无反应?_Win10系统电脑鼠标左键单击没有反应的解决办法
  11. linux下设备树spi的节点查询,已解决: 关于ZYNQ-Linux中设备树SPI节点的疑问 - Community Forums...
  12. 软件测试工程师--面试题
  13. SpringBoot 动态设置响应头的content-type
  14. Flutter 混合开发
  15. 【观察】星环科技重构数据云平台,持续释放数据红利和价值
  16. 分辨率极限-时间分辨率+空间分辨率和图像超分辨重建技术
  17. 等精度测频原理--频率计
  18. NameValuePair
  19. 基于Java+Swing+mysql图书管理系统
  20. 五杆机构正运动学公式、逆运动学公式MATLAB代码

热门文章

  1. 私域引流工具及场景落地方法
  2. 求弹性模量和泊松比计算题_弹性模量E和泊松比
  3. forge 服务器 优化,[1.7.10]模组服务器优化教程-Mod服的超频 - 联机教程 - Minecraft(我的世界)中文论坛 -...
  4. 【C】C语言核心知识点总结(Reference Manual)
  5. linux网卡聚合是什么意思,linux网卡聚合
  6. 多层级的SISR算法
  7. 基带qcn的备份与写入相关 格机 nv报错
  8. 世界上应用最广泛的算法之一的卡尔曼滤波算法原理-从放弃到精通-无人机/机器人应用
  9. 小寒资料集·描写篇 语言表达
  10. 常见算法思想2:递推法