精华内容
下载资源
问答
  • 今天在读《Java开发手册》时,看到浮点数的等值判断问题「浮点数的基本数据类型不能用 == 比较,包装数据类型不能用 equals 比较」。以前开发时也遇到过浮点数的坑,所以就想一探究竟。1. 浮点数表示在计算机系统...

    今天在读《Java开发手册》时,看到浮点数的等值判断问题「浮点数的基本数据类型不能用 == 比较,包装数据类型不能用 equals 比较」。以前开发时也遇到过浮点数的坑,所以就想一探究竟。

    1. 浮点数表示

    在计算机系统理论中,浮点数采用 IEEE 754 标准表示,编码方式是符号+阶码+尾数,如图:

    4679618fd28c

    浮点数表示

    比如 float 类型占用 32 位,单精度浮点表示法:

    符号位(sign)占用 1 位,用来表示正负数,0 表示正数,1 表示负数

    指数位(exponent)占用 8 位,用来表示指数,实际要加上偏移量

    小数位(fraction)占用 23 位,用来表示小数,不足位数补 0

    从这里可以看出,指数位决定了大小范围,小数位决定了计算精度。当十进制数值转换为二进制科学表达式后,得到的尾数位数是有可能很长甚至是无限长。所以当使用浮点格式来存储数字的时候,实际存储的尾数是被截取或执行舍入后的近似值。这就解释了浮点数计算不准确的问题,因为近似值和原值是有差异的。

    2. 比较浮点数的方式

    让我们来验证一下比较浮点数的几种方式。

    1. == 操作符

    比较两个浮点数,一个从零开始加 11 次 0.1,另一个用 0.1 乘以 11 计算。然后用 == 比较大小。

    private void compareByOperator() {

    float f1 = 0.0f;

    for (int i = 0; i < 11; i++) {

    f1 += 0.1f;

    }

    float f2 = 0.1f * 11;

    System.out.println("f1 = " + f1);

    System.out.println("f2 = " + f2);

    if (f1 == f2) {

    System.out.println("f1 and f2 are equal using operator ==");

    } else {

    System.out.println("f1 and f2 are not equal using operator ==");

    }

    }

    运行输出:

    f1 = 1.1000001

    f2 = 1.1

    f1 and f2 are not equal

    可以看到,两个浮点数不相等,所以通过 == 来比较浮点数是不可靠的。

    2. 误差范围

    指定一个误差范围,两个浮点数的差值在范围之内,则认为是相等的。使用 Math.abs() 计算差值,然后和阈值比较。

    private void compareByThreshold() {

    final float THRESHOLD = 0.000001;

    float f1 = 0.0f;

    for (int i = 0; i < 11; i++) {

    f1 += 0.1f;

    }

    float f2 = 0.1f * 11;

    System.out.println("f1 = " + f1);

    System.out.println("f2 = " + f2);

    if (Math.abs(f1 - f2) < THRESHOLD) {

    System.out.println("f1 and f2 are equal using threshold");

    } else {

    System.out.println("f1 and f2 are not equal using threshold");

    }

    }

    运行输出:

    f1 = 1.1000001

    f2 = 1.1

    f1 and f2 are equal using threshold

    3. 使用 BigDecimal

    BigDecimal 是不可变的,能够精确地表示十进制数字。需要注意的是,创建 BigDecimal 对象时,要使用参数为 String 的构造方法,不要使用构造参数为 double 的,如果非要使用 double 创建,一定要用 valueOf 静态方法,防止丢失精度。然后调用 compareTo 方法比较即可。

    private void compareByBigDecimal() {

    BigDecimal f1 = new BigDecimal("0.0");

    BigDecimal pointOne = new BigDecimal("0.1");

    for (int i = 0; i < 11; i++) {

    f1 = f1.add(pointOne);

    }

    BigDecimal f2 = new BigDecimal("0.1");

    BigDecimal eleven = new BigDecimal("11");

    f2 = f2.multiply(eleven);

    System.out.println("f1 = " + f1);

    System.out.println("f2 = " + f2);

    if (f1.compareTo(f2) == 0) {

    System.out.println("f1 and f2 are equal using BigDecimal");

    } else {

    System.out.println("f1 and f2 are not equal using BigDecimal");

    }

    }

    运行输出:

    f1 = 1.1

    f2 = 1.1

    f1 and f2 are equal using BigDecimal

    3. 结论

    使用 == 比较浮点数不准确,可以采用误差范围近似相等,或者 BigDecimal 计算比较。

    展开全文
  • java 浮点数精度

    2018-08-10 10:38:32
    本文参考自: 原文地址 ...二进制浮点数不能精确的表示0.1、0.01、0.001这样10的负次幂。并不是所有的小数都能可以精确的二进制浮点数表示。 java.math包下面的两个有用的类:BigInteger和BigD...

    本文参考自: 原文地址

    由于字长有限,浮点数能够精确表示的数是有限的,因而也是离散的。 浮点数一般都存在舍入误差,很多数字无法精确表示(例如0.1),其结果只能是接近, 但不等于。二进制浮点数不能精确的表示0.1、0.01、0.001这样10的负次幂。并不是所有的小数都能可以精确的用二进制浮点数表示。

            java.math包下面的两个有用的类:BigInteger和BigDecimal,这两个类可以处理任意长度的数值。BigInteger实现了任意精度的整数运算。BigDecimal实现了任意精度的浮点运算。


    表示方法

    BigDecimal.valueOf(1.0)

    展开全文
  • 展开全部并java浮点数精度会丢失,而是所有用二进制存e69da5e6ba903231313335323631343130323136353331333365643662储中的浮点数都可能会...小数在转换为二进制时并一定能用一个精确的二进制表示,大多数时...

    展开全部

    并不是java的浮点数精度会丢失,而是所有用二进制存e69da5e6ba903231313335323631343130323136353331333365643662储中的浮点数都可能会精度丢失(部分特殊的小数数值可以精确表示),所以计算机中存储的浮点数都存在精度丢失的风险,不过一边这个丢失的精度对我们正常的使用不会构成影响。

    小数在转换为二进制时并不一定能用一个精确的二进制表示,大多数时候都是取的一个近似值,这就造成了精度的丢失。如果再用这个二进制进行计算,明显计算结果的精度会进一步丢失。

    举个简单的例子把0.1用二进制表示(小数与二进制转换方法)(1) 0.1 x 2 = 0.2  取整数位 0 得 0.0

    (2) 0.2 x 2 = 0.4  取整数位 0 得 0.00

    (3) 0.4 x 2 = 0.8  取整数位 0 得 0.000

    (4) 0.8 x 2 = 1.6  取整数位 1 得 0.0001

    (5) 0.6 x 2 = 0.2  取整数位 1 得 0.00011

    (6) 0.2 x 2 = 0.4  取整数位 0 得 0.000110

    (7) 0.4 x 2 = 0.8  取整数位 0 得 0.0001100

    (8) 0.8 x 2 = 1.6  取整数位 1 得 0.00011001

    (9) 0.6 x 2 = 1.2  取整数位 1 得 0.000110011

    (n) ...

    得到一个无限循环的二进制小数 0.000110011…,没办法用一个精确的二进制表示0.1。而且计算机中存储一个浮点数所用的位数也是有限的,所以只能选择在某一个精度进行保存。

    当然也有特殊的小数,比如0.25的二进制为0.01

    展开全文
  • 之所以会出现本不能精确表示的浮点数在打印出来后反而是精确的,是因为在将其转换为字符串的过程中,Java耍了点小聪明。它会将看起来疑似是“整”的浮点数进行特殊处理,转换为那个“整”的十进制小数形式。举个例子...

    恰好自己有过一点研究。

    首先可以肯定,出现这种现象的原因并不是发生在二进制数的表示阶段,0.1确实无法用二进制浮点数精确表示,这个毋庸置疑。

    之所以会出现本不能精确表示的浮点数在打印出来后反而是精确的,是因为在将其转换为字符串的过程中,Java耍了点小聪明。它会将看起来疑似是“整”的浮点数进行特殊处理,转换为那个“整”的十进制小数形式。

    举个例子,比如0.1,如果按内部表示直接转换过来可能应该是0.1000...0011,这种情况下,最后两位的数值太小,Java就会认为是精度不够而产生的,于是转成字符串的时候会将其转为0.1。

    而0.4/4和0.4-0.3,由于参与计算的时候,都至少有一个是不能精确表示的数,所以结果可能会有一定的误差。按照前面的例子,可能0.4/4的结果为0.1000...0010,最后一位与真正的0.1不同,而0.4-0.3的结果为0.1000...0300,这个误差就比较大了。

    注:以上仅仅是我臆想的值,并不是真实的数据。能够说明问题即可。

    由于两者误差不同,所以0.4/4的结果仍然会被认为是“整”的小数0.1,但0.4-0.3却由于累计的误差较大而被认为不是0.1,而是原样转换为0.1000...03。

    展开全文
  • 准确,bigdecimal
  • 为什么java不能用浮点数控制for循环? double k; for(k=0.1;k<2.0;k+=0.1) { System.out.println(k); } 结果: 0.1 0.2 0.30000000000000004 0.4 0.5 0.6 0.7 0.7999999999999999 0.8999999999999999 0....
  • 之所以会出现本不能精确表示的浮点数在打印出来后反而是精确的,是因为在将其转换为字符串的过程中,Java耍了点小聪明。它会将看起来疑似是“整”的浮点数进行特殊处理,转换为那个“整”的十进制小数形式。举个例子...
  • 比如 数字1/5,我们能用十进制小数 0.2 准确的表示,但是我们却不能把它准确的表示为一个二进制小数,我们只能通过增加二进制表示的长度来提高表示的精度。如下:那我们该怎么办呢?1、舍入对于不能精确的表示的数,...
  • 注前面写了一个超大整数相加的类参见 超大整数相加超过了long的范围你要怎么做后来有朋友评论说BigDecimal可以完全实现我的这这个功能刚开始的时候我还服气据我所知那里有这样的类哦后来报着说服他的心理去找了...
  • 四:不能用浮点数来表示金额  1)精度丢失问题  从上面我们可以知道,float的精度是23位,double精度是63位。在存储或 运算过程 中,当超出精度时,超出部分会被截掉,由此就会造成误差。  对于金额而言,...
  • 四:不能用浮点数来表示金额 1)精度丢失问题 从上面我们可以知道,float的精度是23位,double精度是63位。在存储或运算过程中,当超出精度时,超出部分会被截掉,由此就会造成误差。 对于金额而言,舍去不能表示的...
  • java浮点数精度

    2018-07-14 21:13:45
    二进制浮点数不能精确的表示0.1、0.01、0.001这样10的负次幂。并不是所有的小数都能可以精确的二进制浮点数表示。    java.math包下面的两个有用的类:BigInteger和BigDecimal,这两个类可以...
  • java浮点数的比较

    2021-01-13 10:31:16
    不能用“==”直接比较 原因: float和double类型都不能用于严格要求精度的计算,这是因为float和double类型使用的都是IEEE 754标准,而这种标准的表示范围和表示精度有限,根据标准,将不能表示的范围舍去。所以,...
  • 之所以会出现本不能精确表示的浮点数在打印出来后反而是精确的,是因为在将其转换为字符串的过程中,Java耍了点小聪明。它会将看起来疑似是“整”的浮点数进行特殊处理,转换为那个“整”的十进制小数形式。举个例子...
  • 计算机是一种二进制格式存储小数的,这个二进制格式不能精确表示0.1,它只能表示一个非常接近0.1但又不等于0.1的一个数。数字都不能精确表示,在不精确数字上的运算结果不精确也就不足为奇了。0.1怎么会不能精确...
  • 因此浮点数不能精确表示。也造成计算有误差。 如果浮点数和整型进行运算,整型会先提升为浮点型,再进行运算,结果为浮点型。double d = 1 - 9.0 /10;//0.09999999999999998double d1 = 1.2 ...
  • Java-浮点数判断相等

    2018-02-12 16:44:20
    1.单纯实际定义的浮点数,可以用“==”: double a=1.2; double b=1.2; if(a==b) System.out.println("yes");...2.但是加入其中一个浮点数是通过计算得出来的,就不能用“==”: double a=1.0; doubl
  • Java浮点数相等性比较

    千次阅读 2020-10-02 15:10:33
    今天在读《Java开发手册》时,看到浮点数的等值判断问题「浮点数的基本数据类型不能用 == 比较,包装数据类型不能用 equals 比较」。以前开发时也遇到过浮点数的坑,所以就想一探究竟。 1. 浮点数表示 在计算机...
  • 四:不能用浮点数来表示金额 1)精度丢失问题 从上面我们可以知道,float的精度是23位,double精度是63位。在存储或运算过程中,当超出精度时,超出部分会被截掉,由此就会造成误差。 对于金额而言,舍去不能表示的...
  • Java中的浮点数比较

    2020-12-07 12:02:01
    浮点数不能用==判断是否相等,但是>或者<可以。 https://blog.csdn.net/dodott/article/details/53410756 https://www.cnblogs.com/zhloong/p/java-float-number-compare.html 比如JDK中Float的compareTo...
  • 浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals 来判断。说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进 Java 开发手册 8/44 制...
  • 浮点数的基本数据类型不能用==比较,包装数据类型不能用 equals 比较浮点数的表示在计算机系统中,浮点数采用 符号+阶码+尾数 进行表示。在Java中,单精度浮点数float类型占32位,它的二进制表示方式为:符号位:1位...
  • java学习—浮点数

    2018-11-11 14:09:42
    一、浮点数 浮点数的double是最常用的,float是有时难以满足精度要求。 二、浮点数的误差 ...BigDecimal类型的数据不能和float和double类型的数据比较大小。 当减得幅度很大并且次数少时输出结果可能不...
  • 浮点数格式3.1 为什么不能用浮点数存储金额4. 移码4.1 机器中所使用的偏移量4.2 为什么要使用移码4.3 为什么不是2^n-1^参考材料前言码出高效这本书以前翻到浮点数这一页的时候随便看一下过了就过了,最近再次开始翻...
  • 在比较大小时,千万不能用下面这种方式来比较大小 System.out.println(0.1+0.2 == 0.3); 这是很危险的,很显然,结果是false 在计算机中存储的都是二进制数,十进制中的一些有限小数,如:0.3在计算机中存储就有...
  • 1.1二进制表示为:1.000110……,即0.1 = 0*2^(-1)+0*2^(-2)+0*2^(-3)+1*2^(-4)+……而double型的小数部分只有52位,当向后计算 52位后基数还不为0时,后面的部分只能舍弃,从这里可以看出float型、double型并不能...
  • 《阿里巴巴Java开发手册》中提到:浮点数之间的等值判断,基本数据类型不能用==来比较,包装数据类型不能用 equals 来判断。 具体原理和浮点数的编码方式有关,这里就不多提了,我们下面直接上实例: float a = 1.0f...
  • Java中如何比较浮点数是否相等

    千次阅读 2017-09-20 14:10:14
    1.值相等浮点数能表示的精度是有限的,在计算过程中可避免的会出现截尾而损失精度,而且传感器等外部设备输入的数据本身也有误差,所以如果要判断一个浮点数double_x是否等于0,double_x == 0这样的判断是合适的...
  • 这篇文章主要记录一些关于精度问题的小知识,当然也不知道对不对,先记录一下~啦啦啦~我是勤劳的屌丝程序猿 少年...我们不能用“==”来判断浮点数是否相同,WHY?? 1. 浮点数的存储格式 对于float: 符号位S(1) 阶

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 381
精华内容 152
关键字:

java浮点数不能用

java 订阅