博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
二进制那些事
阅读量:7205 次
发布时间:2019-06-29

本文共 2206 字,大约阅读时间需要 7 分钟。

中介绍到计算机内部由集成电路决定了计算机的信息只能用二进制数处理。本期将介绍二进制那些事。

移位运算

移位运算指的是将二进制数值的各数位进行左右移位的运算。左移空出来的低位要进行补0操作,右移空出来的高位要进行怎样的操作,我们会在后面说明。

image.png

我们发现,左移两位相当于对39乘以4,右移两位相当于除4,也就是说计算机用移位算法来表示数据的乘除运算

补数

刚才之所有没有介绍相关右移的内容,是因为用来填充右移后空出来的高位的数值,有 0 和 1 两种形式。要想区分什么时候补0什么时候补1,只要掌握了用二进制数表示负数的方法即可。

二进制数中表示负数时,一般会把最高位作为符号来使用,也就是说,最高位是符号位。正数的符号位用0表示,负数的符号位用1表示。举个栗子,1的二进制数是0000 0001 ,那么,-1的二进制数是多少呢?难道是1000 0001,1000 0001+0000 0001 结果不是0,说明这个结果是错的。为此,在表示负数时就需要使用补数补数就是用正数表示负数,通过将二进制数的各位数值全部取反,然后再将结果加1得到补数。-1的补数是1111 1111。同理,1111 1110表示的负数是多少呢?这时我们可以利用负负得正这个性质。假设1111 1110是负xx,那么1111 1110的补数是正xx。1111 1110的补数是0000 0010,因此1111 1110表示-2。

逻辑右移和算术右移

在介绍完补数后,让我们返回到右移这个话题,右移之后在最高位有补0和补1两种情况。当二进制数的值表示图形模式而非数值时,移位后在最高位补0,这是逻辑右移。将二进制数值作为带符号的数值进行运算时,移位后要在最高位填充前符号位的值( 0 或 1 ),这是算术右移

现在我们来看一个右移的例子。将-8(1111 1000)右移两位。这时,逻辑右移的情况下结果会是 0011 1110,也就是十进制数62,显然不是-2,而在算术右移的情况下,结果会变成1111 1110 ,用补数表示就是-2,和真实结果相同。需要注意的是只有在右移时才区分逻辑移位和算术移位。

二进制数表示小数

通过上述介绍,我们对整数的二进制表示方式做了说明。由于计算机内部所有信息都是以二进制数的形式来处理,因此在这一点上,整数和小数并无差别。不过,使用二进制数表示整数和小数的方法却有很大的不同。

由于二进制数表示的小数的数值范围是有限的,并不能表示所有的十进制小数。例如:小数点后3位用二进制数表示时的数值范围为0.000~0.111,但是只能表示有限的十进制小数,如下图所示。

image.png
为了加深大家印象,举一个更加实际的栗子:将0.1累加100次最终结果是10.000002,不是10。

public class TestBinary {    public static void main(String[] args) {        float sum=0.0f;        for (int i = 0; i < 100; i++) {            sum += 0.1;        }        System.out.println(sum);    }}

浮点数

现在,我们应该知道仅仅依靠纸面上的二进制数是表示不了全部小数。那么,计算机实际上是以什么样的表现形式来处理小数的呢?

目前,计算机提供了单精度浮点数和双精度浮点数来表示小数形式。单精度浮点数用32位表示全体小数,而双精度浮点数用64位表示。它们都是由符号、尾数和指数组成。

image.png

接下来,让我们一起看一下如果将0.1用单精度浮点数来表示,累加100次的结果是否是10,可以结果又一次出乎意料,结果是10.000002。

public class TestBinary {    public static void main(String[] args) {        float sum=0.0f;        float step = 0.1f;        for (int i = 0; i < 100; i++) {            sum += step;        }        System.out.println(sum);    }}

如何避免计算机计算出错

我们知道,无论是用纸面二进制还是浮点数表示小数,都存在计算出错的可能性,那么我们该如何避免这种问题呢?

首先是回避策略,即无视这些问题。有时候一些微小的偏差并不会造成什么问题。其次,把小数转换成整数来计算。还是以0.1累加100次为例,将0.1扩大10倍后累加100次,最后把结果除以10就可以了。

public class TestBinary {    public static void main(String[] args) {        int sum=0;        int step = 1;        for (int i = 0; i < 100; i++) {            sum += step;        }        System.out.println(sum/10);    }}

转载于:https://blog.51cto.com/13712434/2107865

你可能感兴趣的文章
Linux命令(21)查看文件的行数
查看>>
java 高精度 四则运算
查看>>
CreateEvent(...)函数在线程通信中的秘密!
查看>>
java struts2 debug
查看>>
20165330 2017-2018-2 《Java程序设计》第4周学习总结
查看>>
MongoDB快速入门
查看>>
linux 安装 nginx 及反向代理配置
查看>>
转 11g RAC R2 体系结构---Grid
查看>>
transition-分栏按钮动画
查看>>
[你必须知道的异步编程]——基于任务的异步模式
查看>>
lxml.etree 教程4:Elements contain text
查看>>
09 常见事件响应
查看>>
【LeetCode 228_数组】Summary Ranges
查看>>
java.lang.ArithmeticException: / by zero
查看>>
JAVA 类与对象题目3
查看>>
centos7系统备份与还原
查看>>
黑白灰,色彩厚涂
查看>>
机器学习 — 决策树建模
查看>>
弹射起步~django
查看>>
C# 中的 == 和 equals()有什么区别?
查看>>