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

基本数据类型

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

字节型与整型的边界问题

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,完全正确。但别忘了-128的二进制表达形式:1000 0000(2) 也就是说,上述的计算转化为二进制就是:

minn+1 = 1000 0000 + 1 = 1000 0001

-127的二进制表示竟然是1000 0001(2) ,这明显与我们的常识不符,计算机内部的计算方式肯定有什么不同。在这里就要用到补码的知识,这篇博客 写的很不错。

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

有趣的浮点数

浮点数的存储方式

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

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 V=(1)SM2E
注:

  1. ( − 1 ) S (-1)^S (1)S表示符号位,当S=0,V为整数,S=1,V为负数。
  2. M表示有效数字,且 1 &lt; = M &lt; = 2 1&lt;=M&lt;=2 1<=M<=2但因为计算机内部为二进制存储,为了节约空间,我们可以默认第一位是1,而不记录首位的1,只记录小数点后的部分,当需要将该数取出的时候,才把1加上。因此,真正记录在计算机中的M是 0 &lt; = M &lt; = 1 0&lt;=M&lt;=1 0<=M<=1的。
  3. 2 E 2^E 2E表示指数位。为了使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

大致是这个意思。

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

[这学期博主刚刚学完计算机组成原理,发现上面讲的很多地方都不太准确,只是原码的表现形式,初学者看着留个印象就好 2019.7.19]

浮点数的精度问题

根据以上所学知识,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);
	}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值