《深入理解计算机系统:信息的表示和处理》读书笔记(一)

《深入理解计算机系统:第二章》读书笔记(一)

《深入理解计算机系统:第二章》-信息的表示和处理,分了四节,分别是信息存储整数的表示整数的运算浮点数,由于书上的知识太理论了,这里不好总结,加上由于自己工作内容接触java比较多,接下来,为了学习整数的表示及其运算,动手写了一个测试案例。

测试案例如下:

public class NumAppliaction {
    public static void main(String[] args) {
        int intNum = 500 * 600 * 100 * 200;
        System.out.println("intNum十进制:" + intNum);
        System.out.println("intNum二进制:" + Integer.toBinaryString(intNum));
        System.out.println("intNum八进制:" + Integer.toOctalString(intNum));
        System.out.println("intNum十六进制:" + Integer.toHexString(intNum));

        /** 注意1 在java程序中'^' 表示异或,不能表示乘方的意思**/
        int a = 2 ^ 10 + 2 ^ 11 + 2 ^ 12 + 2 ^ 13 + 2 ^ 15 + 2 ^ 21 + 2 ^ 23 + 2 ^ 24 + 2 ^ 26 + 2 ^ 29 + 2 ^ 30;

        /** 注意2 在Java运算优先级中,'+' 的优先级大于 '<<' 如书上所说,在不了解优先级的情况下,最好先带上括号**/
        int b = (2 << 9) + (2 << 10) + (2 << 11) + (2 << 12) + (2 << 14) + (2 << 20) + (2 << 22) + (2 << 23) + (2 << 25) + (2 << 28) + (2 << 29);
        System.out.println(a);
        System.out.println(b);
        System.out.println("-------------------------------------------------");

        /** 注意3 在做系列加减乘除运算时,都有可能导致越界溢出,得到意想不到的结果,比如下面转化之前的运算**/
        long intTolongNum = 500 * 600 * 100 * 200;
        System.out.println("intTolongNum十进制:" + intTolongNum);
        System.out.println("intTolongNum二进制:" + Long.toBinaryString(intTolongNum));
        System.out.println("intTolongNum八进制:" + Long.toOctalString(intTolongNum));
        System.out.println("intTolongNum十六进制:" + Long.toHexString(intTolongNum));
        System.out.println("-------------------------------------------------");

        /** 注意4 int与long类型相乘,得到的结果就是long类型的,所以不会产生越界**/
        long longNum = 500 * 600 * 100 * 200L;
        System.out.println("longNum十进制:" + longNum);
        System.out.println("longNum二进制:" + Long.toBinaryString(longNum));
        System.out.println("longNum八进制:" + Long.toOctalString(longNum));
        System.out.println("longNum十六进制:" + Long.toHexString(longNum));

        /** 注意5 2 << 31 默认为int类型,越界后为0**/
        long c = (2 << 9) + (2 << 10) + (2 << 11) + (2 << 12) + (2 << 14) + (2 << 20) + (2 << 22) + (2 << 23) + (2 << 25) + (2 << 28) + (2 << 29) + (2 << 31);
        System.out.println(c);
        /** 2的32次方**/
        long intMax = 4294967296L;
        /** 注意6 二进制转十进制 应该将其中的一个因子置为long类型**/
        long d = (2 << 9) + (2 << 10) + (2 << 11) + (2 << 12) + (2 << 14) + (2 << 20) + (2 << 22) + (2 << 23) + (2 << 25) + (2 << 28) + (2 << 29) + intMax;
        System.out.println(d);
    }
}

输出


intNum十进制:1705032704
intNum二进制:1100101101000001011110000000000
intNum八进制:14550136000
intNum十六进制:65a0bc00
26
1705032704
-------------------------------------------------
intTolongNum十进制:1705032704
intTolongNum二进制:1100101101000001011110000000000
intTolongNum八进制:14550136000
intTolongNum十六进制:65a0bc00
-------------------------------------------------
longNum十进制:6000000000
longNum二进制:101100101101000001011110000000000
longNum八进制:54550136000
longNum十六进制:165a0bc00
1705032704
6000000000

  • 知识点一: 数值越界
    *

    • 可以看到500 * 600 * 100 * 200的计算结果是int类型,存储越界溢出了,导致程序打印意想不到的结果。
    • 但是这里为什么会打印1705032704呢?
    • 我们来看一下500 * 600 * 100 * 200=6000000000这个二进制:1 0110 0101 1010 0000 1011 1100 0000 0000。由于int类型的数值占四个字节,一字节八位,因此总共32位,其无符号可表示的数值范围为【0~4294967295】,有符号可表示的数值范围为【-2147483647~2147483648】,由于java只支持有符号数,因此6000000000是越界的(占了33位),那么读取字符时,int类型只能读到32位,即0110 0101 1010 0000 1011 1100 0000 0000,转化为十进制的话,就是1705032704。
  • 知识点二:位运算 与 位移运算
    *

    • 可以看出,上面程序中我犯了一个错误,我将‘^’符当作数学中乘方使用了(我记得之前也犯过一次这个错,这个错真的太容易犯了,希望长个记性)。
    • 扩展
      • 位运算使用的运算符有‘&’——运算,‘|’——运算,‘~’——运算,‘^’——’异或‘符
      • 在书上的练习题2.13中,我们可以得到一个公式 x^y=(x&~y)|(y&~x)
      • 位移运算包含左位移,右位移(又分逻辑右移和算术右移),都是右移,只是算术右移区分符号,与逻辑右移相比,唯一的区别是:负数的算术右移最高位补1
  • 知识点三:数值参与运算,运算结果的字节长度取决于计算因子中最大字节长度
    *

    • 在代码long intTolongNum = 500 * 600 * 100 * 200中,我们打印intTolongNum的值也没有得到我们期望的值,是什么原因引起的呢?
    • 是因为java语言中,加减乘除所有运算的,算出来的结果按照最大字节长度取值,比如short与int类型相加是int类型,int类型的与long类型的相加,结果是long类型,这个好像就是叫类型转化。
    • 只有当long longNum = 500 * 600 * 100 * 200L 这么使用时,才能得到我们期望的值。
  • 知识点四:运算优先级
    *

    • 在Java运算优先级中,’+’ 的优先级大于 ‘<<’ 如书上所说,在不了解优先级的情况下,最好先带上括号
    • 符号运算优先级如下
      在这里插入图片描述
    • 注意,java运算符?:,+=,^=,>>>=,默认是从右往左运算。
  • 知识点五:十进制,二进制,八进制与十六进制数之间的转化
    *

    • 十进制与二进制的转化

      • 十进制转二进制

        250除二取余数,后面的余数居最高位,得11111010

      • 二进制转十进制

        27+26+25+24+23+21=128+64+32+16+8+2=250

    • 二进制与八进制的转化

      • 二进制转八进制

        11111010补全前面的位数,9位(3的倍数)得011 111 010,得372

      • 八进制转二进制

        八进制372,每一位转化为二进制3->011,7->111,2->010,得011 111 010

    • 二进制与十六进制的转化

      • 二进制转十六进制

        11111010补全前面的位数,8位(4的倍数)得1111 1010,得0xFA

      • 十六进制转二进制

        十六进制0xFA,每一位转化为二进制F->1111,A->1010,得1111 1010

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值