当前位置: 首页 > news >正文

java中如何比较两个浮点型大小

浮点数的表示

在计算机系统中,浮点数采用 符号+阶码+尾数 进行表示。

在这里插入图片描述

在Java中,单精度浮点数float类型占32位,它的二进制表示方式为:

  • 符号位:1位,0表示正数; 1表示负数
  • 指数位:8位,用来表示指数(要加上偏移量)
  • 小数位:23位,用来表示小数

实际上计算机中的浮点数表示方法和科学技术法类似,小数的位数决定了浮点数的精度。当一个十进制的小数转换成二进制时,很有可能无法使用这么多小数位表示它。因此使用浮点数的时候,实际存储的尾数是被截取或者舍入之后的值。因此使用浮点数进行计算的时候就不得不考虑精度问题,即浮点数无法精确计算。

如何比较浮点数

对于浮点数,我们无法使用==或者包装类型的equals()来精确比较,尽管无法做到精确比较,但是我们可以确定一个误差范围,当小于这个误差范围的时候就认为这两个浮点数相等。

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


为什么使用double的构造参数就会丢失精度?

代码:

System.out.println(new BigDecimal(0.99D));	// 0.9899999999999999911182158029987476766109466552734375

System.out.println(BigDecimal.valueOf(0.99D));	// 0.99

输出:

表面上看起来第一行数字更长,但是我们传的是0.99,它却是0.98…所以损失了精度

    public static BigDecimal valueOf(double val) {
        return new BigDecimal(Double.toString(val));
    }

那么使用BigDecimal.valueOf(double val)就一定精确吗?
不是。

代码:

double val = 0.989999999999999111D;
System.out.println(Double.toString(val));   //0.9899999999999991
System.out.println(BigDecimal.valueOf(val));    //0.9899999999999991

当数值超过了double的精度范围,Double.toString()方法也是无法精确表示的。要使用参数为 String 的构造方法才能保证compareTo()的结果是精确的。

System.out.println(new BigDecimal("0.989999999999999111")); //0.989999999999999111

代码

如果可以确保数值不会超过double的精度范围,一定要比较两个浮点型大小,比如不会出现0.989999999999999111这样超过double所能表示的范围的数值,那么:

    public static int doubleCompare(double a, double b) {
        BigDecimal bd1 = BigDecimal.valueOf(a);
        BigDecimal bd2 = BigDecimal.valueOf(b);
        return bd1.compareTo(bd2);
    }

来自:
Java比较两个浮点数 - zhloong - 博客园
Java比较浮点数的正确方式 - 简书

Java中new BigDecimal()和BigDecimal.valueOf() - djangson小站
java - BigDecimal - to use new or valueOf - Stack Overflow
BigDecimal如何使用new或valueOf? - 问答 - 云+社区 - 腾讯云
new BigDecmal (double)精度问题及与BigDecimal.valueOf(double)的区别_u013514816的博客-CSDN博客

相关文章:

  • 了解 BigDecimal.valueOf(double val)与new BigDecimal(double val) 的区别
  • 数值的整数次方 -- java
  • Could not get a resource from the pool 的原因之一
  • 打印从1到最大的n位数 -- java
  • 删除链表节点 -- java
  • npm 查看是否安装了某个包
  • 正则表达式匹配 -- java
  • 表示数值的字符串 -- java
  • 调整数组顺序使奇数位于偶数前面 -- java
  • 链表中倒数第K个节点 -- java
  • Mac查看npm安装位置
  • idea env: node: No such file or directory
  • 链表中环的入口节点 -- java
  • 反转链表 -- java
  • 合并两个排序的链表 -- java
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • angular组件开发
  • Django 博客开发教程 8 - 博客文章详情页
  • iOS 颜色设置看我就够了
  • js作用域和this的理解
  • JWT究竟是什么呢?
  • Node项目之评分系统(二)- 数据库设计
  • Python学习之路16-使用API
  • Sass Day-01
  • 动态魔术使用DBMS_SQL
  • 记录:CentOS7.2配置LNMP环境记录
  • 近期前端发展计划
  • 开源SQL-on-Hadoop系统一览
  • 目录与文件属性:编写ls
  • 悄悄地说一个bug
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 学习使用ExpressJS 4.0中的新Router
  • 一起参Ember.js讨论、问答社区。
  • ​比特币大跌的 2 个原因
  • #控制台大学课堂点名问题_课堂随机点名
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (二)PySpark3:SparkSQL编程
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (正则)提取页面里的img标签
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .Net Core 中间件验签
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • /usr/bin/perl:bad interpreter:No such file or directory 的解决办法
  • :中兴通讯为何成功
  • @kafkalistener消费不到消息_消息队列对战之RabbitMq 大战 kafka
  • [ vulhub漏洞复现篇 ] AppWeb认证绕过漏洞(CVE-2018-8715)
  • [Android] Upload package to device fails #2720
  • [Asp.net MVC]Bundle合并,压缩js、css文件
  • [C语言][C++][时间复杂度详解分析]二分查找——杨氏矩阵查找数字详解!!!