11.30

发布时间 2023-12-18 18:59:01作者: 孙锺鸣

阅读相应教材,或者使用互联网搜索引擎,弄清楚反码、补码跟原码这几个概念,然后编写示例程序,对正数、负数进行各种位操作,观察输出结果,与手工计算的结果进行比对,看看Java中的数是采用上述哪种码表示的。
解答:
1. 原码

原码就是符号位加上真值的绝对值,即用第一位表示符号,其余位表示值。比如:如果是8位二进制:

[+1]原= 0000 0001

[-1]原= 1000 0001

第一位是符号位,因为第一位是符号位,所以8位二进制数的取值范围就是:(即第一位不表示值,只表示正负。)

[1111 1111 , 0111 1111]

[-127 , 127]

原码是人脑最容易理解和计算的表示方式。

2. 反码

反码的表示方法是:

正数的反码是其本身;

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

[+1] = [0000 0001]原= [0000 0001]反

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

可见如果一个反码表示的是负数,人脑无法直观的看出来它的数值。通常要将其转换成原码再计算。

3. 补码

补码的表示方法是:

正数的补码就是其本身;

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

[+1] = [0000 0001]原= [0000 0001]反= [0000 0001]补

[-1] = [1000 0001]原= [1111 1110]反= [1111 1111]补

对于负数,补码表示方式也是人脑无法直观看出其数值的。通常也需要转换成原码再计算其数值。

 

Java变量遵循“同名变量的屏蔽原则”,请课后阅读相关资料弄清楚相关知识,然后自己编写一些测试代码,就象本示例一样,有意识地在不同地方定义一些同名变量,看看输出的到底是哪个值。

同名变量的屏蔽原则:每个变量都有一个有效区域,即定义的那片区域,出了这个区域,变量将不再有效。(全局变量除外)

举例:

package test;

public class Test {
private static int value= 1;
public static void main(String[] args) {
int value= 2;
System.out.println(value);
}

 

输出结果为2

 

 看着这个图,再查查Java中每个数据类型所占的位数,和表示数值的范围,你能得出什么结论?

 

 byte:    1字节 -128~127
short:   2字节 -2^15~2^15-1
int :      4字节 -2^31~2^31-1
long:    8字节 -2^63~2^63-1
boolean:1字节 true false(java中不能以0或非0代替)
float:    4字节 -3.403E38~3.403E38
double:8字节 -1.798E308~- 4.9E324
char:    2字节  ’\u0000‘~‘ ’\uffff ‘(16进制的,换算过来即0~65535)

自动类型转换是安全的,强制类型转换时,可能会引起信息的损失。实线代表无精度损失,虚线代表有精度损失,一般来说在实线两端都是由低精度指向高精度的类型,所占的位数从低到高,范围从小到大,所以可得出,低精度向高精度转化不丢失精度,反之,从高精度传向低精度则会损失。

 

请运行以下代码(TestDouble.java),你看到了什么样的输出,意外吗?

import java.util.Scanner;
 
public class TestDouble {
 
    public static void main(String args[]) {
 
        System.out.println("0.05 + 0.01 = " + (0.05 + 0.01));
 
        System.out.println("1.0 - 0.42 = " + (1.0 - 0.42));
 
        System.out.println("4.015 * 100 = " + (4.015 * 100));
 
        System.out.println("123.3 / 100 = " + (123.3 / 100));
 
    }
 
}

结果截屏如下:

 

解答:意外,使用double类型的数值进行计算,结果是不精确的。

 

为什么double类型的数值进行运算得不到“数学上精确”的结果?
解答:Double类型的数值占用64bit,即64个二进制数,除去最高位表示正负符号的位,在最低位上一定会与实际数据存在误差,简单地说就是我们给出的数值,在大多数情况下需要比64bit更多的位数才能准确表示出来,而double类型的数值只有64bit,后面舍去的位数一定会带来误差,无法得到“数学上精确”的结果。

 

以下代码的输出结果是什么?为什么会有这样的输出结果?

int X=100;
        int Y=200;
        System.out.println("X+Y="+X+Y);
        System.out.println(X+Y+"=X+Y");

结果截屏如下:

 

在System.out.println()中,如果在string字符串后面是+和变量,会把变量转换成string类型,加号起连接作用,然后把两个字符串连接成一个新的字符串输出;如果先有变量的加减运算再有字符串,那么会从左到右先计算变量的加减,然后再与后面的string结合成一个新的字符串。也就是说加号只有在两个string类型或者其中一个是string类型的时候才起到连接作用,否则仍然是运算符