java数据类型的转换以及精度丢失_long转double会丢失精度吗_ღLiJia的博客-CSDN博客
一.浮点类型在计算机当中的存储
- float存储需求是4字节(32位), 其中1位最高位是符号位,中间8位表示阶位,后32位表示值
- float的范围: -2^128 ~ +2^128,也即-3.40E+38 ~ +3.40E+38
- float的精度: 2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字
- double存储需求是8字节(64为),其中1位最高位是符号位,中间11位表示阶位,后52位表示值
- 取值范围: -2^1024 ~ +2^1024,也即-1.79E+308 ~ +1.79E+308
- 精度: 2^52 = 4503599627370496,一共16位,同理,double的精度为15~16位
- long数据类型是64位有符号Java原始数据类型。
- 取值范围: -9223372036854775808到9223372036854775807 (”-2^64“ 到”2^64 -1)
精度丢失就是我们的位数不够表示我们整个数值了
问题原因:
首先计算机进行的是二进制运算,我们输入的十进制数字会先转换成二进制,进行运算后再转换为十进制输出。Float和Double提供了快速的运算,然而问题在于转换为二进制的时候,位数不够表示我们整个数值,有些数字不能完全转换,只能无限接近于原本的值,这就导致了在后来的运算会出现不正确结果的情况。
整体转换图
如图所示,其中:
- 实线byte→short、short→int、int→long、int→double、char→int、float→double转换是不会发生精度丢失的,因为后者所包含的范围比前者大且完全包含前者。
- 而虚线int转float、long转float,long转double都会发生精度丢失。精度丢失包括两种,一是有效数字丢失,一是目标类型完全无法表示数据
原因如下:
int和float都是32位,但是内存结构也就是存储结构是不一样的,float只有24(含隐含的一位整数位)位来确定精度,而int是32位。long转float,long转double精度丢失原理是一样
详解:
我们知道,float的存储结构是1个符号位,8个指数位,23个尾数。
- 符号位,表述浮点数的正或者负,0代表正,1代表负。
- 指数位,实际也是有正负的,但是没有单独的符号位,在计算机的世界里,进位都是二进制的,指数表示的也是2的N次幂,8位指数表达的范围是0到255,而对应的实际的指数是-127到128。也就是说实际的指数等于指数位表示的数值减127。
- 尾数位,只代表了二进制的小数点后的部分,小数点前的那位被省略了,当指数位全部为0时省略的是0否则省略的是1。
所以可以说,实际上尾数确定了浮点数的精度,而数的大小主要是靠指数位,尾数只有23位,加上隐含的一位整数位便是24位。也就是说int类型的值在2^24以内,float是可以精确表示的,但是当超过这个数的时候就不一定能精确表示了。其他类型也是如此。
取值范围:
1、int。
- 最小值:Integer.MIN_VALUE= -2147483648 (-2的31次方)
- 最大值:Integer.MAX_VALUE= 2147483647 (2的31次方-1)
2、double。
- 最小值:Double.MIN_VALUE=4.9E-324 (2的-1074次方)
- 最大值:Double.MAX_VALUE=1.7976931348623157E308 (2的1024次方-1)
- 负值取值范围为: -1.7976E+308 到 -4.94065645841246544E-324,
- 正值取值范围为: 4.94065645841246544E-324 到 1.797693E+308
- (e+308表示乘以10的308次方,而e-324 表示乘以10的负324次方)
- float有效数字8位,double有效数字16位
3、long。
- 最小值:Long.MIN_VALUE=-9223372036854775808 (-2的63次方)
- 最大值:Long.MAX_VALUE=9223372036854775807 (2的63次方-1)
4、float 。
- 最小值:Float.MIN_VALUE=1.4E-45 (2的-149次方)
- 最大值:Float.MAX_VALUE=3.4028235E38 (2的128次方-1)
- (e+38 表示乘以10的38次方,而e-45 表示乘以10的负45次方)
System.out.println("Long.MAX_VALUE: ---> " + Long.MAX_VALUE);
System.out.println("Double.MAX_VALUE: ---> " + new Double(Double.MAX_VALUE).longValue());
System.out.println("Double.MAX_VALUE: --->" + new Double(1.797693e+308).longValue());
// 打印结果
Long.MAX_VALUE: ---> 9223372036854775807
Double.MAX_VALUE: ---> 9223372036854775807
Double.MAX_VALUE: --->9223372036854775807
二、 Java数据类型及转换原则
赋值和方法调用转换规则:从低位类型到高位类型自动转换,从高位类型到低位类型需要强制类型转换:
(1)布尔型和其它基本数据类型之间不能相互转换;
(2)byte型可以转换为short、int、、long、float和double;
(3)short可转换为int、long、float和double;
(4)char可转换为int、long、float和double;
(5)int可转换为long、float和double;
(6)long可转换为float和double;
(7)float可转换为double;
其中,int转换为char类型,float类型都需要强转,会导致精度丢失
long转换为double也需要强转,会导致精度丢失。
三、打印数值
char类型的最大值:127
char类型的最小值:-128
signed char类型的最大值:127
signed char类型的最小值:-128
unsigned char类型的最大值:255short类型的最大值:32767
short类型的最小值:-32768
unsigned short类型的最大值:65535int类型的最大值:2147483647
int类型的最小值:-2147483648
unsigned int类型的最大值:4294967295long类型的最大值:2147483647
long类型的最小值:-2147483648
unsigned long类型的最小值:4294967295float类型的尾数位数:24
float类型的最小有效数字位数:6
带有全部有效数字位数的float类型的负指数的最小值:38
带有全部有效数字位数的float类型的正指数的最大值:-37
保留全部精度的float类型正数的最小值:1.175494e-038
保留全部精度的float类型正数的最大值:3.402823e+038
1.00和比1.00大的最小的float类型值之间的差值:1.192093e-007double类型的尾数位数:53
double类型的最小有效数字位数:15
带有全部有效数字位数的double类型的负指数的最小值:308
带有全部有效数字位数的double类型的正指数的最大值:-307
保留全部精度的double类型正数的最小值:2.225074e-308
保留全部精度的double类型正数的最小值:1.797693e+308
1.00和比1.00大的最小的double类型值之间的差值:2.220446e-016long double类型的尾数位数:64
long double类型的最小有效数字位数:18
带有全部有效数字位数的long double类型的负指数的最大值:4932
带有全部有效数字位数的long double类型的正指数的最小值:-4931
保留全部精度的long double类型正数的最小值:3.205284e-317
保留全部精度的long double类型正数的最大值:3.205284e-317
1.00和比1.00大的最小的long double类型值之间的差值:3.205284e-317