重学java-3.基本数据类型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/euzmin/article/details/88194066

基本数据类型

本文会举例一些小的边界问题与类型转化问题,引出对底层浅尝辄止的讨论。

字节型与整型的边界问题

byte和整型在计算机中的存储方式是一样的,都是整数的存储。

这里这里我们以byte为例,因为byte的数据范围最小,看起来比较直观。

下面是我写的一个简单程序:

public static void main(String[] args) {
		byte maxx = Byte.MAX_VALUE;
		byte minn = Byte.MIN_VALUE;
		System.out.println(maxx+" "+minn);
		++maxx;
		--minn;
		System.out.println(maxx+" "+minn);
}

运行结果:
运行结果1
maxx代表byte的最大范围,minn代表byte的最小范围。

我们发现,当执行++maxx和- -minn操作后,maxx与minn仿佛发生了置换。为什么会这样?

这是因为计算机中的数据是以 二进制 存储的。
让我们从byte的取值范围 -128~127 入手:

byte是一个字节占8位内存,通常第一位代表符号位(0代表正数,1代表负数)。因此,最大范围为
0111 1111(2)=127(10)。但这样 1000 0000(2)=-0(10) 就没有意义了,为了节省计算机内存,我们约定
1000 0000(2)=-128(10)

有了上面的知识前提后,回到之前的讨论,maxx与minn仿佛发生了置换的原因就不难想到了:

maxx+1 = 0111 1111 + 1 = 1000 0000
minn-1 = 1000 0000 - 1 = 0111 1111

当然,边界问题还远远没有结束。按照我们一般的逻辑,minn+1的值会是多少呢?

public static void main(String[] args) {
		
		byte minn = Byte.MIN_VALUE;
		System.out.println("minn: "+minn);
		++minn;
		System.out.println("minn: "+minn);
	}

在这里插入图片描述
是的,-127,完全正确。但别忘了-127的二进制表达形式:1111 1111(2) 也就是说,上述的计算转化为二进制就是:

minn+1 = 1000 0000 + 1 = 1111 1111

这明显与我们的常识不符,计算机内部的计算方式肯定有什么不同。在这里就要用到补码的知识,这篇博客 写的很不错。

在我阅读这篇博客时,读到全加器的概念,感觉很陌生。如果您也有这样的困惑,建议阅读这篇博客

有趣的浮点数

浮点数的存储方式

与整型不同,浮点数的存储方式分为三个部分。

IEEE 754规定对于32位的浮点数,最高的1位是符号位S,接着的8位是指数E,剩下的23位为有效数字M。
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。

而任意一个二进制浮点数V可以表示为下面的形式:
V = ( 1 ) S M 2 E V = (-1) ^S * M * 2^E
注:

  1. ( 1 ) S (-1)^S 表示符号位,当S=0,V为整数,S=1,V为负数。
  2. M表示有效数字,且 1 < = M < = 2 1<=M<=2 但因为计算机内部为二进制存储,为了节约空间,我们可以默认第一位是1,而不记录首位的1,只记录小数点后的部分,当需要将该数取出的时候,才把1加上。因此,真正记录在计算机中的M是 0 < = M < = 1 0<=M<=1 的。
  3. 2 E 2^E 表示指数位。为了使E能表示负数,E的值在存入计算机时,需加上127(E为8位)或1023(E为11位)。同时,为了能表示一些特殊的事,我们还得分三种情况讨论E:
    (1).E不全为0且E不全为1。这是正常情况,需要计算时,将其值减去127或1023即可得到真实值。
    (2).E全为0。这时,E等于1-127或1-1023,有效数字M不用加上第一位的1,而是还原为0.xxx的小数。这样做是为了表示正负0,以及非常接近于0的数。
    (3).E全为1。这时,如果M全为0,表示正负无穷大(正负取决于符号位s);如果有效数字M不全为0,表示这个数不是一个数(NaN)。

例如:

-5.5 = 1101.1 = (-1)^1 * 1.011 * 2^2

大致是这个意思。

以上概念是我在码农有道里看的一篇文章学的。

浮点数的精度问题

根据以上所学知识,0.2的浮点数该如何表达呢?首先得把0.2转化为二进制,等等,0.2显然根本就无法转化为二进制(无限循环)。

public static void main(String[] args) {
		double a = 0.8;
		double b = 1.0;
		System.out.println(b-a);
		if(b - a == 0.2) {
			System.out.println("按理说是这样");
		} else {
			System.out.println("惊了");
		}
	}

是的,结果正如我们所想:
在这里插入图片描述
java是利用MathBigDecimal的四舍五入函数解决这个问题的。

类型转换

类型转换分为 强制类型转换自动类型转换 两种。

  • 自动类型转换:当数据范围小的数据转化为数据范围大的数据时,小数据类型将自动转化为大数据类型。
  • 强制类型转换:当数据范围大的数据要变为数据范围小的数据时,必须要使用强制类型转化。

就本人目前的学习而言,只有在算法题中会经常用到类型转换,而在项目中其实反而要避免出现类型转换的情况。

一个简单的例子:

public static void main(String[] args) {
		
		int a = 1;
		double b = a; //自动类型转换
		System.out.println("a: "+a+" b: "+b);
		int c = (int) b; //强制类型转换
		System.out.println("b: "+b+" c: "+c);
	}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/euzmin/article/details/88194066
今日推荐