Java深海拾遗系列(1)---java浮点型数操作准确性问题刨析

原创 2017年01月02日 21:05:30

计算机中的数据存储有整型和浮点型两种形式。
整型是用二进制形式来表示所有正整数和负整数以及零,由于存储空间的限制,只能表示一定范围的整数。在Java中,整型byte,short,int,long,用来表示不同范围的整数。
浮点型则是用二进制的科学计数法形式来表示实数,由于存储空间的限制,不可能精确存储所有的实数,有些实数只能用四舍五入的近似形式存储。浮点型则有float和double用来表示不同精度和范围的浮点数。

浮点型表达的不精确问题

案例一:

public static boolean compareFloatValue(){
float expectedValue = 1.0f;
float realValue =0.0f;
for (int i=0;i<10;i++) {
    realValue +=0.1f;
}
//expectedValue==realValue is false
return expectedValue==realValue;
}

案例二:

double result = 1.0 - 0.9;
//result 0.09999999999999998
System.out.println("result " +result);

案例三:

float larger =10000000.00000f;
float smaller =0.00001f;
//结果是 1.0E7
System.out.print(larger+smaller);

由于精度问题,double/float比较相等也不能直接使用==,但是比较大小可以用<、 >号

double d1 = 0.1, d2 = 0.1;  
if (d1 == d2) {}// 坏代码  
if (Double.compare(d1, d2) == 0) {}// 好代码  
if (Double.doubleToLongBits(d1) == Double.doubleToLongBits(d2)) {}// 好代码  
if (Double.valueOf(d1).equals(d2)) {}// 好代码,1.5以上  

解决浮点数运算不准确问题方法

用NumberFormat类来格式化计算结果

double result = 1.0 - 0.9;  
NumberFormat nf = NumberFormat.getInstance();// 根据自己的需求格式化  
String resultStr = nf.format(result); 

使用long ,int等基本类型

int resultInt = 10 - 9;  
double result = (double) resultInt / 100;//最终时候自己控制小数点 

使用BigDecimal来代替double

String result = new BigDecimal("1").subtract(new BigDecimal("0.9")) .toString(); 

使用第三方工具类

apache的commons-lang的math包,主要有4大类功能
1. 处理分数的Fraction类,分数表示数字,更为精确。

Java代码 
Fraction fraction = Fraction.getFraction(10, 3);// 三分之十  
System.out.println(fraction);// 10/3  
System.out.println(fraction.floatValue());// 3.3333333  
System.out.println(fraction.doubleValue());// 3.3333333333333335  
System.out.println(fraction.toProperString());// 三又三分之一  
System.out.println(fraction.reduce());// 约分,如2/4约分后1/2  
  1. 处理数值的NumberUtils类;这个比较简单,看看api就可以。封装了一些常用数字操作方法,如数字转换、比较,获取一个数字数组中最大值,最小值等。
  2. 处理数值范围的Range、NumberRange、IntRange、LongRange、FloatRange、DoubleRange类;

    Java代码
    // 拿int举例,其他类似
    IntRange intRange = new IntRange(100, 200);// 创建一个范围
    intRange.containsDouble(111.1);// 是否包含指定数字
    int[] range = intRange.toArray();// 获取范围内的int
    intRange.getMaximumDouble();// 获取最大值,转换成double
    intRange.getMinimumDouble();// 获取最小值,转换成double

  3. 处理随机数的JVMRandom和RandomUtils类。这个也比较简单,看看api就可以,获取随机数时比较方便而已。

其他

  • 类型声明
    longNum1即使声明为long类型,但是由于没有在数字末尾加上L字符,所以编译器还是以默认的int类型进行存储,longNum2是正确的long类型的声明方式,longNum3由于长度已经超出int类型能够支持的长度,但是又没有在数字末尾加L字符编译器就报错了。

    long longNum1 = 2;
    long longNum2 = 500000000000000000L;
    long longNum3 = 500000000000000000;//提示编译错误

  • 极限值
    正无穷:Double.POSITIVE_INFINITY;
    负无穷:Double.NEGATIVE_INFINITY;
    NaN:Double.NaN;
    并且判断一个数字是否为NaN也应该采用下面的方式
    if(Double.isNaN(Double.NaN)){
    }
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

Java数值避免浮点型计算丢失精度问题

问题描述及方案 假设我们在做电商项目,在进行计算时这个丢失精度在产品价格计算就会出现问题,很有可能造成我们手里有9.99元然后后面会有一堆9,但是呢这些钱无法购买一个10元的商品。 在某些编程语言中...

Java中的浮点型(Double&Float)计算问题

Java中的浮点数类型float和double不能够进行精确运算。比如,double型直接计算,1.4×1.5有时会得出2.0999999999999996的结果,但实际上,应该得到2.10。而且,类...
  • yin_jw
  • yin_jw
  • 2014年04月11日 16:11
  • 943

Java中的浮点型进行四则运算精度丢失的问题

Android开发过程中需要有很多的商业运算,这些运算中会出现对float类型和double类型的四则运算。单纯拿float和double进行四则运算就会出现很大的精度丢失问题。为了解决这个问题,建议...

【JAVA基础系列】IEEE754二进位浮点算数标准-JAVA转换器实现

将32位浮点数转换为IEEE754格式 32位浮点数IEEE754格式位: 1位符号位 + 8位指数位 + 23位尾数 转换思路: 1、计算整数部分的二进制格式; 2、计算小数部分的二进制格式; 3、...
  • mhl29
  • mhl29
  • 2016年05月14日 16:56
  • 1578

java浮点计算精度丢失问题

import java.math.BigDecimal; /** * 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精 * 确的浮点数运算,包括加减乘除和四舍五入。 ...

Java知识点拾遗1

基本成员默认值若一个类的某个成员是基本数据类型,即使没有进行初始化,Java也会确保它获得一个默认值。但局部变量(非成员变量)则是默认随机取值。 基本类型 默认值 boolean fal...

JAVA浮点型的加法

  • 2012年03月24日 02:02
  • 228B
  • 下载

java计算器(整型+浮点型)

  • 2012年11月11日 15:58
  • 56KB
  • 下载

Java数值计算工具类NumberUtil(防止java计算产生浮点问题)

import java.math.BigDecimal; import java.text.DecimalFormat; import java.util.regex.Matcher; import ...

java中浮点型的格式输出(DecimalFormat)

转自:点击打开链接 在输出数字时,有时需要给数字配上单位,有时需要数字具有一定的精度,也有时需要用科学计数法表示数字。 关键技术剖析: v java.text.DecimalFormat类专门用于格式...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java深海拾遗系列(1)---java浮点型数操作准确性问题刨析
举报原因:
原因补充:

(最多只允许输入30个字)