float范围值的大小(面试题float和double类型的表示范围和精度)

Java面试题之浮点数float浮点数判断大小有陷阱,因为底层的二进制数不能精确表示所有的小数。有时候会产生让人觉得莫名其妙的事情。Java浮点数float和double类型的表示范围和精度对于f

Java面试题之浮点数float

float范围值的大小(面试题float和double类型的表示范围和精度)

浮点数判断大小有陷阱,因为底层的二进制数不能精确表示所有的小数。有时候会产生让人觉得莫名其妙的事情。

Java 浮点数 float和double类型的表示范围和精度

float范围值的大小(面试题float和double类型的表示范围和精度)

对于float来说,4个字节,32位,0-22位表示尾数,23-30(8位)表示指数,31位表示符号位。

float范围值的大小(面试题float和double类型的表示范围和精度)

对于double来说,8个字节,64位,0-51表示尾数,52-62(11位)表示指数,63位最高位表示符号位。

float范围值的大小(面试题float和double类型的表示范围和精度)

float和double的精度是由尾数的位数来决定的。

浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,由于它是不变的,故不能对精度造成影响。

float:2^23 = 8388608,一共七位,由于最左为1的一位省略了,这意味着最多能表示8位数: 2*8388608 = 16777216 。有8位有效数字,但绝对能保证的为7位,也即float的精度为7~8位有效数字;

double:2^52 = 4503599627370496,一共16位,同理,double的精度为16~17位。

10 进制中,无法准确表达 1/3:

1/3 = 3.333333 x 10^-1

2 进制中,也无法准确表达 0.1:

上述题目的计算过程

float范围值的大小(面试题float和double类型的表示范围和精度)

float范围值的大小(面试题float和double类型的表示范围和精度)

float 变量 a 和b 的比较是严格比较每一位上面的0和1,因此上述2个变量的比较是不相等的。

float范围值的大小(面试题float和double类型的表示范围和精度)

浮点数使用建议

货币之类的精确表示使用整型来存储,计算,表示上进行数值的相互转化。

尽量使用double,而不是 float,中间的计算结果,如果是局部变量,可以使用 double 来进行。但是,存储的时候,建议使用整型或BigDecimal。

扩展思考

进一步提供几个代码示例:

(1)将 float 改用double 类型

public class DoublePrimitiveTest {

public static void main(String[] args) {

double a = 1.0 - 0.9;

double b = 0.9 - 0.8;

if(a == b){

System.out.println(\"true\");

} else {

System.out.println(\"false\");

}

if(a == 0.1){

System.out.println(\"a==0.1\" + \" true\");

} else {

System.out.println(\"a!=0.1\");

}

System.out.println(a);

System.out.println(b);

}

}

输出结果:

true

a!=0.1

0.09999999999999998

0.09999999999999998

建议:

double的计算不精确,会有类似0.0000000000000002的误差,正确的方法是使用BigDecimal或者用整型。整型地方法适合于货币精度已知的情况,比如12.11+1.10转成1211+110计算,最后再/100即可。

(2)改用BigDecimal 类型

import java.math.BigDecimal;

public class BigDecimalPrimitiveTest {

public static void main(String[] args) {

BigDecimal m = new BigDecimal(1.0);

BigDecimal n = new BigDecimal(0.9);

BigDecimal l = new BigDecimal(0.8);

BigDecimal a = m.subtract(n);

BigDecimal b = n.subtract(l);

if(a.equals(b)){

System.out.println(\"true\");

} else {

System.out.println(\"false\");

}

if(a.equals(new BigDecimal(0.1))){

System.out.println(\"a==0.1\" + \" true\");

} else {

System.out.println(\"a!=0.1\");

}

System.out.println(a);

System.out.println(b);

}

}

输出结果:

true

a!=0.1

0.09999999999999997779553950749686919152736663818359375

0.09999999999999997779553950749686919152736663818359375

BigDecimal的euquals方法是先判断要比较的数据类型,如果对象类型一致前提下同时判断精确度(scale)和值(BigInteger的equals方法)是否一致。

本站部分文章来自网络或用户投稿,如无特殊说明或标注,均为本站原创发布。涉及资源下载的,本站旨在共享仅供大家学习与参考,如您想商用请获取官网版权,如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
科技百科

LTE网络是什么(带你了解LTE基本原理)

2023-5-18 17:42:27

科技百科

查看Linux系统版本的命令有哪些(分享8 种查看版本方法)

2023-5-18 17:42:32

搜索