1. 初识JVM

JVM的概念

略过

JVM发展历史

略过

JVM种类

略过

Java语言规范

主要定义语法、变量、类型、文法之类的信息

略过

JVM规范

主要定义Class文件类型、运行时数据、祯栈、虚拟机的启动、虚拟机的指令集之类的信息

Java语言和JVM相对独立(以下语言皆使用JVM,符合JVM规范)

  • Groovy
  • Clojure
  • Scala

1. 整数的表达()

  • 原码:第一位为符号位(0为正数,1为负数)
  • 反码:符号位不动,原码取反
  • 负数补码:符号位不动,反码加1
-6
原码: 10000110
反码: 11111001
补码: 11111010

-1
原码: 10000001
反码: 11111110
补码: 11111111
  • 正数补码:和原码相同
5
00000101
  • 打印整数的二进制表示
int a=-6;
for(int i=0;i<32;i++){
    int t=(a & 0x80000000>>>i)>>>(31-i);
    System.out.print(t);
}

2. 为什么要用补码?

  • 没有歧义的表示0(无论看作正数还是负数)
0
正数:00000000

负数:10000000
反码:11111111
补码:00000000

  • 源码计算难以得到期望的结果;补码计算、符号位参与运算就能得到正确的结果
-6+5          -4+5
  11111010      11111100
+ 00000101    + 00000101
= 11111111    = 00000001

3. float的表示与定义

详见此文件夹下的文件:float的表示

s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm

指数:8 尾数:23

e全0 尾数附加位为0 否则尾数附加位为1

s * m * 2^(e-127)


作业

  1. 有关补码,简要阐述补码的好处。并计算给出 -99, -105, 205 整数的补码

答:a. 可以无歧义的表示0;

0为正数
原码、补码 00000000

0为负数
原码 10000000
反码 11111111
补码 00000000

b. 使用原码计算可能得不到想要的结果,而使用补码,符号位参与运算能得到准确的结果。

-99                 -105                205
原码 1110,0011      原码 1110,1001       0000,0000,1100,1101
反码 1001,1100      反码 1001,0110
补码 1001,1101      补码 1001,0111
  1. 有关浮点数,根据IEEE745,计算1,10000010,00100000000000000000000的单精度浮点的值,并给出计算过程。

答:公式为 s * m * 2^(e-127)

e=1000,0010=2^1+2^7=130
m=1+2^-3=1.125
v=-2^(130-127) * 1.125=-9

3.写一个Java程序,将100.2转成IEEE745 二进制表示 ,给出程序和结果。

    /**
     * 将输入的double转成IEEE745二进制表示
     * @param d 要转换的浮点数
     */
    public static void printDouble(double d){
        //最终要输出的值
        StringBuilder dStr = new StringBuilder();
        
        /* 1. 将浮点数d的整数和小数分别表示成二进制形式  */
        int integer = (int) d;  //整数值
        double decimals = d - integer;  //小数值
        System.out.println("小数值为: " + decimals);
        //整数值的二进制表示
        String integerStr = Integer.toBinaryString(integer);
        //小数值的二进制表示
        StringBuilder decimalStr = new StringBuilder();
        int count = 32; //小数取位数32位
        for (int i = 0; i < count; i++) {
            decimals = decimals * 2;
            if(decimals > 1){   //整数部分取1
                decimalStr.append(1);
                decimals -= 1;
            }else{  //整数部分取0
                decimalStr.append(0);
            }
        }
        System.out.println("整数部分的二进制为: " + integerStr);
        System.out.println("小数部分的二进制为: " + decimalStr);
        
        /* 2. 填充符号位 */
        dStr.append(d > 0?0:1);
        
        /* 3. 左移或者右移小数点到第一个有效数字 */
        /* 4. 小数点移位数加127后取二进制填充到e值 */
        if(integer > 0){    //取有效数字,小数点左移
            //根据整数二进制字符串长度来确定左移位数
            int bit = integerStr.length() -1;
            dStr.append(Integer.toBinaryString(bit + 127)); //填充e值
            decimalStr.insert(0, integerStr.substring(1));   //将整数部分移位后的值插入到小数部分前面
        }else{  //取有效数字,小数点右移
            //暂时不需要实现
        }
        
        // 5. 小数点后取23位填充到m值
        dStr.append(decimalStr.subSequence(0, 23)); //填充m值
        System.out.println("100.2的IEEE745二进制表示为: " + dStr);
        
    }

输出结果为:

整数部分的二进制为: 1100100
小数部分的二进制为: 00110011001100110011001100110011
100.2的IEEE745二进制表示为: 01000010110010000110011001100110

你可能感兴趣的:(1. 初识JVM)