zoukankan      html  css  js  c++  java
  • 读书笔记:C++ Primer系列(2)—— 整型赋值问题

    知识储备:

    1. 有符号数与无符号数

         有符号数和无符号数是针对二进制来讲的。

         有符号数用最高位作为符号位,“0”代表“+”,“1”代表“-”;其余数位用作数值位,代表数值。
         无符号数全部二进制均代表数值,没有符号位。即第一个"0"或"1"不表示正负。

    例如:

    无符号数: 1111 1111    值:255         1* 27 + 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20 
    有符号数: 0111 1111    值:127          1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20 

    同样是一个字节,无符号数的最大值是255,而有符号数的最大值是127。无符号的最小值是 0 ,而有符号数的最小值是-128。即:

                                                  无符号数:                        0 ----------------------- 255 
                                                  有符号数:                  -127 --------- 0 ------------ 127        也可记成         -128 --------- 0 ------------ 127  

    2. 机器数、真值、原码、反码、补码

    •     机器数

        一个数在计算机中的二进制表示形式,  叫做这个数的机器数。机器数是带符号的,在计算机中用一个数的最高位存放符号, 正数为0, 负数为1。

        比如:以单字节(8位)为例,十进制数+5,转换成二进制为:0000 0101,十进制数-5,转换为二进制为:1000 0101;其中的0000 0101和1000 0101就是+5和-5在计算机中的机器数。

    •     真值

        将带符号位的机器数的真正数值称为这个数的真值。

        比如:带符号数:0000 0011的真值=+000 0011=+3; 1000 1001的真值=-000 1001=-7

    •     原码

        原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值。(我的理解:原码就是某个数的机器数或者是二进制形式)。以单字节为例:

                                                   [+1]=0000 0001          [-1]=1000 0001 

        因为第一位是符号位,所以单字节数的取值范围是[1111 1111     0111 1111]即[-127    +127]     

    •     反码

        反码的表示规则:

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

                                                    [+1]=0000 0001          [-1]=1111 1110

    •     补码

        补码的表示规则:

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

                                                    [+1]=0000 0001          [-1]=1111 1111

     

    从上面可以看到,原码、反码、补码是完全不同的,而我们计算机中存放数值是存放的补码,这是为什么呢?为什么计算机不直接采用原码或反码呢?

    这是因为考虑到减法问题,且看下面分析

                                                           [+1] = [0000 0001] = [0000 0001] = [0000 0001]

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

    计算十进制数1与1相减:1-1=0

          如果计算机采用原码,就会出现:1-1=1+(-1)=[0000 0001]+ [1000 0001]=[1000 0010]=-2,结果显然不对。

          如果计算机采用反码,就会出现:1-1=1+(-1)=[0000 0001]+[1111 1110]=[1111 1111]=[1000 0000]=-0,显然也不是我们想要的结果,因为在0前面加上”+“或”-“没有意义。

          如果计算机采用补码,则1-1=1+(-1)= [0000 0001]补+ [1111 1111]=[0000 0000]=[0000 0000]=0,符合预期结果

    这里有一个问题:当用补码计算(-1)-(127)时,应该是-128

          -1-127=(-1)+(-127)=[1111 1111]+[1000 0001]=[1000 0000]

    注:在用补码运算的结果中, [1000 0000] 就是-128。 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示。

          对-128的补码表示[1000 0000]补算出来的原码是[0000 0000],这是不正确的。

    $关于整型的赋值问题

          C++ Primer(第四版)P32提到:对象的类型决定对象的取值。疑问:当把一个超出其取值范围的值赋给一个指定类型的对象时,结果如何?-——答案为取决于这种类型的是signed还是unsigned的。

          比如对于8位的unsigned char类型,其取值范围为0到255(包含255),如果赋给超出这个范围的值,那么编译器会取该值对256求模后的值。如:将336赋给一个8位的unsigned char中,则实际赋值为80(因为80是336对256求模后的值)

         而对于unsigned类型来说,负数总是超出其取值范围的。但C++中,将负数赋值给一个unsigned对象是完全合法的,其结果是该负数对该类型的取值个数求模后的值。

         如:将-1赋给8位的unsigned char,则结果是255(-1 mod 256=255)

         这里涉及到负数进行mod运算,公式如下:

     

        

       

  • 相关阅读:
    LocalImprove算法
    Improve算法
    CSU-ACM2014年校队选拔赛指导赛解题报告
    CSU-ACM暑假集训基础组训练赛(4)解题报告
    CSU-ACM暑假集训基础组七夕专场
    CSU-ACM暑假集训基础组训练赛(2) 解题报告
    CSU-ACM2014暑假集训基础组训练赛(1) 解题报告
    Aizu 2164 CSUOJ 1436 Revenge of the Round Table
    插头DP小结
    Codeforces 128C Games with Rectangle
  • 原文地址:https://www.cnblogs.com/kkdd-2013/p/3479157.html
Copyright © 2011-2022 走看看