赞
踩
原理:一个正整数 x 若以n位二进制表示,设i为各二进制位的值(0或1),k为各二进制位的权重,则有
∑
i
=
1
n
i
∗
2
k
=
x
\sum_{i=1}^ni*2^k = x
∑i=1ni∗2k=x
例如
101010
b
=
1
∗
2
5
+
0
∗
2
4
+
1
∗
2
3
+
0
∗
2
2
+
1
∗
2
1
+
0
∗
2
0
=
42
10 1010b =1*2^{5} +0*2^{4} +1*2^{3} +0*2^{2} + 1*2^{1}+0*2^{0} = 42
101010b=1∗25+0∗24+1∗23+0∗22+1∗21+0∗20=42
其中指数为0的项已经不能被2整除了,于是我们可以得到:
1
∗
2
5
+
0
∗
2
4
+
1
∗
2
3
+
0
∗
2
2
+
1
∗
2
1
=
42
−
0
∗
2
0
=
42
1*2^{5} +0*2^{4} +1*2^{3} +0*2^{2} + 1*2^{1} = 42 - 0*2^{0} = 42
1∗25+0∗24+1∗23+0∗22+1∗21=42−0∗20=42
将左右两边除以2,得到:
10101
b
=
1
∗
2
4
+
0
∗
2
3
+
1
∗
2
2
+
0
∗
2
1
+
1
∗
2
0
=
21
10101b=1*2^{4} +0*2^{3}+1*2^{2} +0*2^{1}+ 1*2^{0}= 21
10101b=1∗24+0∗23+1∗22+0∗21+1∗20=21
其中指数为0的项已经不能被2整除了,于是我们可以得到:
1
∗
2
4
+
0
∗
2
3
+
1
∗
2
2
+
0
∗
2
1
=
21
−
1
∗
2
0
=
20
1*2^{4} +0*2^{3}+1*2^{2} +0*2^{1}= 21- 1*2^{0} = 20
1∗24+0∗23+1∗22+0∗21=21−1∗20=20
两边除以2,得到:
1010
b
=
1
∗
2
3
+
0
∗
2
2
+
1
∗
2
1
+
0
∗
2
0
=
10
1010b=1*2^{3}+0*2^{2} +1*2^{1} +0*2^{0}= 10
1010b=1∗23+0∗22+1∗21+0∗20=10
其中指数为0的项已经不能被2整除了,于是我们可以得到:
1
∗
2
3
+
0
∗
2
2
+
1
∗
2
1
=
10
−
0
∗
2
0
=
10
1*2^{3}+0*2^{2} +1*2^{1}= 10- 0*2^{0} = 10
1∗23+0∗22+1∗21=10−0∗20=10
两边除以2,得到:
101
b
=
1
∗
2
2
+
0
∗
2
1
+
1
∗
2
0
=
5
101b=1*2^{2} +0*2^{1}+1*2^{0} = 5
101b=1∗22+0∗21+1∗20=5
其中指数为0的项已经不能被2整除了,于是我们可以得到:
1
∗
2
2
+
0
∗
2
1
=
5
−
1
∗
2
0
=
4
1*2^{2} +0*2^{1}=5-1*2^{0}=4
1∗22+0∗21=5−1∗20=4
…
可以看到每次除以2,不能被整除的部分即余数都是二进制低位的值,就这样一直求,一直到被2除完,最终我们会从低位到高位地求出42的二进制形式的所有值。
更加具体化的解释是,假设一个整数w = (a1a2a3a5a6a7a8)b ,其中a1~a8取值范围为0或1,每次除以2,在寄存器中表现的都是整体向右移动一位,移出来的数据就是余数,在实际上cpu就是这么做除法的,整体向左移动就是做乘法了。
除二取余,然后倒序排列,高位补零。也就是说,将正的十进制数除以二,得到的商再除以二,依次类推知道商为零或一时为止,然后在旁边标出各步的余数,最后倒着写出来,位数不够高位补零。比如42转换为二进制,如图1短除法写法所示操作。
42除以2得到的余数分别为010101b(b表二进制,下同),然后咱们倒着排一下,42所对应二进制就是101010b
高位不足补零:计算机内部表示数的字节单位是定长的,如8位,16位,或32位。所以,位数不够时,高位补零,比如42转换成8位的二进制以后就是00101010b
(1) 负数在计算机中是以补码的形式存放的。
(2) 补码的计算:先是将对应的正整数(绝对值)转换成二进制后,对二进制按位取反,然后结果加1就得到补码。
(3) 补码的概念:因为计算机只能计算加法,所以减法5-4实际上是在计算5+(-4), 但怎么在计算机中存储表示这个负数-4呢,我们都知道4+(-4)= 0 ,因此只要让(4)0000 0100b在加法寄存器里加另一个二进制数x最后结果等于(0)0000 0000b 就好了,而这个x就是要找的-4的补码。 那计算补码的规律是什么呢?我们发现当我们将1111 1111b 在寄存器中再进1(或说加1)后是1 0000 0000b,但因一个8位的数据放入寄存器中计算后仍然会取后8位数据出来,高位溢出的1会被舍弃掉,故就会变成我们要的零值0000 0000b,所以我们的求-4的补码时首先是让(4)0000 0100b + y = 1111 1111b,求出y然后加1就得到-4的补码了,很容易发现只要将(4)0000 0100b 全部按位取反就能得到y = 1111 1011b。将上述过程逆推就是先求绝对值(4)的二进制形式,然后取反(得到y),然后再加1(得到x)
原理:
0.001
b
=
0
∗
2
−
1
+
0
∗
2
−
2
+
1
∗
2
−
3
=
0.125
0.001b =0*2^{-1} + 0*2^{-2} + 1*2^{-3} =0.125
0.001b=0∗2−1+0∗2−2+1∗2−3=0.125
两边乘以2,得到:
0.01
b
=
0
∗
2
0
+
0
∗
2
−
1
+
1
∗
2
−
2
=
0.25
0.01b =0*2^{0} + 0*2^{-1} +1*2^{-2}=0.25
0.01b=0∗20+0∗2−1+1∗2−2=0.25
其实每次乘以2都是让整个二进制数据向左移动一位,这导致二进制小数点后面紧邻的一位(0或1)会移动到小数点前面,在十进制里面就是小数点前面紧邻的一位的值(0或1),然后忽略整数部分,继续对小数部分求二进制,继续乘以2,… ,直到小数部分完全为0或者我们要表达的浮点数二进制形式的精度已经足够,就可以停止了,按移动到小数点前的顺序,就是我们要求的浮点数的二进制形式。
具体做法:对小数点以后的数乘以2,取结果的整数部分(不是1就是0喽),然后再用小数部分再乘以2,再取结果的整数部分……以此类推,直到小数部分为0或者位数已经够了就OK了。然后把取的整数部分按先后次序排列就OK了,就构成了二进制小数部分的序列,举个例子吧,比如0.125,如图5所示。
二进制如何转十进制,十进制如何转二进制
如果小数的整数部分有大于0的整数时该如何转换呢?如以上整数转换成二进制,小数转换成二进制,然后加在一起就OK了,如图6所示。
哎,其实还是没有说清楚呢
以float单精度类型为例,4个字节共32位,当以24位表示小数部分(±符号位占一位),以8位表示指数部分时,它的最大小数部分能表示的数是 2 23 = 8388608 2^{23}=8388608 223=8388608, 有七位数,但我们不能说它能表示7位有效数字,因为8388609往后的数字就无法存进这23位里面了,所以只能说它能得到6位有效数字,这也是为何格式化打印一个单精度浮点数时统一输出6位的原因了。
浮点数小数转二进制时很可能陷入无限循环里,我们只能按照需要的精度决定计算到那一步停止计算。比如0.3f 转换成二进制就是:
0.3 * 2 = 0.6,取整数部分0
0.6* 2 = 1.2,取整数部分1
0.2 * 2 = 0.4,取整数部分0
0.4 * 2 = 0.8,取整数部分0
0.8 * 2 = 1.6,取整数部分0
0.6 * 2 = 1.2,取整数部分0
…
看到没有,陷入了无限循环中去了,我们只能按照我们想要的精度去决定计算到那一步,后面的就舍弃不要了,因此说计算机无法精确表示浮点数(虽然其中有部分浮点数可以通过有限计算即可得到精确的二进制表示形式,但只要有一个浮点数无法精确计算存储那我们就说无法精确表示浮点数咯)
其中某些高级语言是以字符串“0.3”来存储的,因此打印时还是精确的0.3,但实际上无法精确存储及表示一个数字0.3是所有语言都面临的问题呢!
浮点数的加减法运算过程详解(面向小白的)
计算机组成原理浮点数加减法运算(一看就懂)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。