计算机中数值的编码方式

1.原码

原码在存储方式上,最高位是符号位,其他位是数值位。
如 :
       正数原码:
          3 对应的一个字节的原码:0000 0011B
       负数原码:
         -3 对应的一个字节的原码:1000 0011B

特殊点的是0的存储,0有两种存储方式:
         +0 对应的一个字节的原码:0000 0000B
         -0 对应的一个字节的原码:1000 0000B


注:计算机中的负数不是以原码的方式存储的,而是补码。

2.反码

反码在存储方式上也是最高位时符号位,其他位是数值位。

如:
       正数反码:
          3 对应的一个字节的反码:0000 0011B    //没错,反码正数的表示方式跟原码是一样的
       负数反码:
         -3 对应的一个字节的反码:1111 1100B  //负数则符号位为1,数值位是原码的按位取反   

特殊点跟原码一样,0的存储在反码也有两种存储方式:
         +0 对应的一个字节的反码:0000 0000B
         -0 对应的一个字节的反码:1111 1111B


3.补码

补码在存储方式同上,最高位时符号位,其他位是数值位。但是, 最高位既是符号位,也是数值位。

如:

       正数补码:
          3 对应的一个字节的反码:0000 0011B    //没错,补码的正数与原码、反码一样。
       负数补码:
         -3 对应的一个字节的反码:1111 1101B   //负数则符号位为1,数值位是反码加上1 
         求补码的负数过程即:
            (1)先求反码
            (2)求得的反码加上1
            (3)完成

如已知的一个负数的把补码是0XFFFF,想要知道它是负多少,可以这么求:
             1111 1111 1111 1111B
    反码得:
             0000 0000 0000 0000B
    加1得:
             0000 0000 0000 0001B
   得出:   
            1D
再加上它表示的是一个负数的,所以结果是-1D。

补码的0就只有一种存储方式:0000 0000B
计算机的数值就是采取补码的方式存储的。

总结:原码、反码、补码在正数的存储方式上是一样的。不同的是负数,不过也有一点共同点,就是符号位都是用1来表示这个数是负数。同时,以上三种编码方式称为定点数。


4.移码(增码)

关于移码我查询了很多资料,因为浮点数的阶码是采取移码方式存储的。
但是阶码的移码跟普通的移码不太一样,采取的是127移码,即在原数加上127。而通常的移码是加上128移码。即补码的符号位取反。
看例子:
              普通的移码换算:
                               3D      
                         0000 0011B
           符号位取反
                         1000 0011B
当然,你也可以这么算 3 + 128 = 131。 131D = 1000 0011B
            浮点数中阶码的移码换算
                              3D 
                         0000 0011B
            先减一
                         0000 0010B
            符号位取反
                         1000 0010B
同理,你也可以这么算 3 + 127 = 130. 130D = 1000 0010B

注: 移码中符号位0表示负数, 1表示正数
4.数值的存储方式

4.1 正数,字符
好了,理解了上面就可以看计算机是怎么存取数值的。
对于 int short long 的存储方式,采用的是补码
              short i = 3;
              i在内存中实际上存的是 0000 0000 0000 0011B
           而 
              short i = -3;
             采取补码的方式,即    1111 1111 1111 1101B
而对于unsigned 类型,数的存储也是一样的。不过
             1111 1111 1111 1101B将不解释为-3,而是65535

字符有一套编码,称为ASCII编码,每一个字符对应着一个编码,关于ASCII的编码表我就不贴出来了。
举几个例子:
                 '0'这个字符在编码上是 30H, 所以计算机在存储的时候存的是 30H
                 ‘a’这个字符在编码上是 61H,  所以计算机在存储的时候存的是 61H
                 ‘\0’这是一个字符,这个字符在编码上是 0H,所以计算机直接存0进去。
注意的是,字符'0'并不等于数值0。

4.2 浮点型
浮点型的存储采取的是IEEE754标准。分为三部分(float为例):

                               符号位           阶码              尾数
                        31(1位)       30 ~ 23(8位)   22 ~ 0(23位)

也有人这么记:SEEE EEEE EMMM MMMM MMMM MMMM MMMM MMMM


符号位容易理解, 1 负数, 0正数
阶码:
           如 123.456
       可以表示为 1.23456 * 10^2 这个2表示的就是阶码了。

尾数就是实际上的数值了。不过,要注意,尾数第22 位前面,也就是最高位前面隐藏着一位 1。
例1:
       1.0        
       计算机浮点数存储中是 0 00000000 0000 0000 0000 0000 0000 000B
       也就是 0X00000000
what?
       因为尾数的最高位前面隐藏着一位 1 .
       0                                            符号位
       0000 0000                                阶码       等于     10^0 = 1
       1.0000 0000 0000 0000 0000 000 尾数
所以  尾数×阶码 = 1.0

这个1怎么来的?其实我也不知道,IEEE754的规定把尾数的前面还有个隐藏的1。如果有哪位同学知道的也请告诉我一声 。 thanks~~

例2:123.456这个数用二进制怎么存?

首先,它是一个正数 ,所以符号位为 0。
先别管阶数。
                         123D 换为二进制是: 1111011B

0.456怎么换为二进制?当然,这是有公式的。公式就是把小数点后的值不断乘以2 
                         0.456 × 2 = 0.912
                         0.912 × 2 = 1.824
                         0.824 × 2 = 1.648
                         0.648 × 2 = 1.296
                         0.296 × 2 = 0.592
                         0.592 × 2 = 1.184
                         0.184 × 2 = 0.368
                         0.368 × 2 = 0.736
                         0.736 × 2 = 1.472
                         0.472 × 2 = 0.944
                         0.944 × 2 = 1.888
                         0.888 × 2 = 1.776
                         0.776 × 2 = 1.552
                         0.552 × 2 = 1.104
                         0.104 × 2 = 0.208
                         0.208 × 2 = 0.416
                                 ....
//这个数举得不好,后面我就不贴出来算了。直接贴换算结果:
            0.456 = 0.01110100101111001B
    123.456 = 1111011.01110100101111001B
   也等于:
         1.11101101110100101111001B  这个数就是尾数了。
阶码就是6,不过6要换成移码 即 6 + 127 = 133 = 100110011B

所以123.456存为

0(符号位) 100110011(阶码) 11101101110100101111001(尾数)。注意,尾数最高位有隐藏一位1

例3:已知二进制求浮点数
还是以123.456上面举例
  0 100110011 11101101110100101111001B
先看尾数 
           11101101110100101111001B
加上隐藏的1
           1.11101101110100101111001B
阶码
    100110011B = 133D
    133 - 127 = 6
整理加上阶码后的尾数
    1111011.01110100101111001B
    算小数点的左边
    1111011 = (1 * 2^6) + (1 * 2^5) + (1 * 2^4) + ( 1* 2 ^3) + (0 * 2^2) + (1 * 2 ^ 1) + (1 * 2^0) = 64 + 32 + 16 + 8 + 0 + 2 + 1 = 123
    算小数点的右边
   01110100101111001 = (0 * 2^-1) + (1 * 2^-2) + .... = 456001
后面多出001是因为浮点型是不稳定的存储方式,在运算的过程中存在偏差。所以浮点数运算是一件比较危险的事情。刚好在这个例子中遇到了。真是幸运!

好了,符号位是0,表示为正。最后终于可以得出   0 100110011 11101101110100101111001B = 123.456F。

转载于:https://www.cnblogs.com/Jer-/archive/2013/04/09/3011058.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值