`
stephen830
  • 浏览: 3010546 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JAVA对double或者float的浮点数精度计算控制方法

    博客分类:
  • java
阅读更多
★★★ 本篇为原创,需要引用转载的朋友请注明:《 http://stephen830.iteye.com/blog/260776 》 谢谢支持!★★★

本篇介绍了在JAVA中如何对double或者float的浮点数进行精度计算,在JAVA中提供了多种参数来实现精度的不同控制方式。具体例子如下:

/*
 * Created on 2005-6-5
 * Author stephen
 * Email zhoujianqiang AT gmail DOT com
 * CopyRight(C)2005-2008 , All rights reserved.
 */
package com.soft4j.utility;

import java.math.BigDecimal;

/**
 * 与小数位精度(四舍五入等)相关的一些常用工具方法.
 * 
 * float/double的精度取值方式分为以下几种: <br>
 * java.math.BigDecimal.ROUND_UP <br>
 * java.math.BigDecimal.ROUND_DOWN <br>
 * java.math.BigDecimal.ROUND_CEILING <br>
 * java.math.BigDecimal.ROUND_FLOOR <br>
 * java.math.BigDecimal.ROUND_HALF_UP<br>
 * java.math.BigDecimal.ROUND_HALF_DOWN <br>
 * java.math.BigDecimal.ROUND_HALF_EVEN <br>
 * 
 * @author stephen
 * @version 1.0.0
 */
public final class RoundTool {

    /**
     * 对double数据进行取精度.
     * <p>
     * For example: <br>
     * double value = 100.345678; <br>
     * double ret = round(value,4,BigDecimal.ROUND_HALF_UP); <br>
     * ret为100.3457 <br>
     * 
     * @param value
     *            double数据.
     * @param scale
     *            精度位数(保留的小数位数).
     * @param roundingMode
     *            精度取值方式.
     * @return 精度计算后的数据.
     */
    public static double round(double value, int scale, int roundingMode) {
        BigDecimal bd = new BigDecimal(value);
        bd = bd.setScale(scale, roundingMode);
        double d = bd.doubleValue();
        bd = null;
        return d;
    }

    /**
     * 测试用的main方法.
     * 
     * @param argc
     *            运行参数.
     */
    public static void main(String[] argc) {
        //下面都以保留2位小数为例
    	
        //ROUND_UP
    	//只要第2位后面存在大于0的小数,则第2位就+1
        System.out.println(round(12.3401,2,BigDecimal.ROUND_UP));//12.35
        System.out.println(round(-12.3401,2,BigDecimal.ROUND_UP));//-12.35
        //ROUND_DOWN
        //与ROUND_UP相反
        //直接舍弃第2位后面的所有小数
        System.out.println(round(12.349,2,BigDecimal.ROUND_DOWN));//12.34
        System.out.println(round(-12.349,2,BigDecimal.ROUND_DOWN));//-12.34
        //ROUND_CEILING
        //如果数字>0 则和ROUND_UP作用一样
        //如果数字<0 则和ROUND_DOWN作用一样
        System.out.println(round(12.3401,2,BigDecimal.ROUND_CEILING));//12.35
        System.out.println(round(-12.349,2,BigDecimal.ROUND_CEILING));//-12.34
        //ROUND_FLOOR
        //如果数字>0 则和ROUND_DOWN作用一样
        //如果数字<0 则和ROUND_UP作用一样
        System.out.println(round(12.349,2,BigDecimal.ROUND_FLOOR));//12.34
        System.out.println(round(-12.3401,2,BigDecimal.ROUND_FLOOR));//-12.35
        //ROUND_HALF_UP [这种方法最常用]
        //如果第3位数字>=5,则第2位数字+1
        //备注:只看第3位数字的值,不会考虑第3位之后的小数的
        System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_UP));//12.35
        System.out.println(round(12.3449,2,BigDecimal.ROUND_HALF_UP));//12.34
        System.out.println(round(-12.345,2,BigDecimal.ROUND_HALF_UP));//-12.35
        System.out.println(round(-12.3449,2,BigDecimal.ROUND_HALF_UP));//-12.34
        //ROUND_HALF_DOWN
        //如果第3位数字>=5,则做ROUND_UP
        //如果第3位数字<5,则做ROUND_DOWN
        System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_DOWN));//12.35
        System.out.println(round(12.3449,2,BigDecimal.ROUND_HALF_DOWN));//12.34
        System.out.println(round(-12.345,2,BigDecimal.ROUND_HALF_DOWN));//-12.35
        System.out.println(round(-12.3449,2,BigDecimal.ROUND_HALF_DOWN));//-12.34
        //ROUND_HALF_EVEN
        //如果第3位是偶数,则做ROUND_HALF_DOWN
        //如果第3位是奇数,则做ROUND_HALF_UP
        System.out.println(round(12.346,2,BigDecimal.ROUND_HALF_EVEN));//12.35
        System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_EVEN));//12.35
    }
}



-------------------------------------------------------------
分享知识,分享快乐,希望文章能给需要的朋友带来小小的帮助。
13
1
分享到:
评论
1 楼 lirui_andy 2013-03-14  

引用

//ROUND_HALF_EVEN 
//如果第3位是偶数,则做ROUND_HALF_DOWN 
//如果第3位是奇数,则做ROUND_HALF_UP 
        System.out.println(round(12.346,2,BigDecimal.ROUND_HALF_EVEN));//12.35 System.out.println(round(12.345,2,BigDecimal.ROUND_HALF_EVEN));//12.35


虽然你这里做的结果好像证实了你对HALF_EVEN的解释,但事实上并不是这样。

ROUND_HALF_EVEN是精确地验证要舍去部分与5的大小,并不只是简单看被舍去的这一位。
假如有数字12.345,该规则得到的是12.34 (先不说为什么你这里是12.35,后面解释)
假如有数字12.335,该规则得到的也是12.34,
假如有数字12.34501,该规则得到的是12.35. JAVA API里有详细解释。

再说说你的12.345为什么得到的是12.35呢?也许这只是个巧合。我们知道计算机在处理小数的时候,有很多小数是没办法真正精确的(因为2进制问题), 你的代码里的12.345在jvm里当做double来存储,而这个小数是没法被计算机精确表达的,它的实际值可能是12.345000000000000001221这样,当你用double类型去构造BigDecimal的时候,得到的BigDecimal实例就包含了后面这一长串尾巴,而BigDecimal类认为这一长串尾巴是有用的,于是setScale(2,ROUND_HALF_EVEN)时,它认为该数字并不是在正中间,而是偏向12.35,于是结果就成了12.35 。
不信你可以验证:
使用你的round方法,看round(8.125,2,BigDecimal.ROUND_HALF_EVEN)是否依然是8.12?而不是你想的8.13?
另外你可以System.out.pringln(new BigDecimal(12.345)),看输出结果是否很长。
再对比System.out.pringln(new BigDecimal(8.125)),System.out.pringln(new BigDecimal("12.345")).

相关推荐

    Java中double类型下出现精度计算错误情况下出力方法

    Java中的简单浮点数类型float和double不能够进行运算,因为大多数情况下是正常的,但是偶尔会出现如上所示的问题。这个问题其实不是JAVA的bug,因为计算机本身是二进制的,而浮点数实际上只是个近似值,所以从二进制...

    Java 精确计算-double-float-String

    标题中的"Java 精确计算 - double-float-String"指向的是Java中处理浮点数(double和float)以及字符串表示的数值时可能遇到的精度问题,以及如何通过特定方法实现精确计算。描述中提到的链接指向了一个具体的博客...

    Java实现IEE754 Float类型数据

    在计算机科学领域中,浮点数的表示方式至关重要,尤其是在处理科学计算、图形渲染等对精度有较高要求的应用场景中。IEEE 754标准定义了一种广泛使用的浮点数表示方法,它被用于大多数现代处理器上。本文将详细探讨...

    用java从文件中读取浮点数

    `double`类型的精度更高,通常用于需要高精度计算的场景。 #### 1.2 文件读取机制 在Java中,文件读取通常涉及到输入流(`InputStream`),其中`FileInputStream`是用于读取文件中字节流的具体类。然而,直接使用`...

    Java实现的浮点类的精确计算

    在Java中,浮点数(float和double)是基于IEEE 754标准的,它们使用二进制浮点表示法,这导致在进行除法、乘法、加法和减法等操作时可能会出现非预期的精度损失。例如,两个看似相等的浮点数在计算后可能因为舍入...

    java-16进制4字节转Float

    在Java中,浮点数有两种主要形式:单精度浮点数(float)和双精度浮点数(double),它们分别使用32位和64位来存储。 1. **字节序**:在进行16进制到浮点数的转换时,必须考虑到字节序,即字节在内存中的排列顺序。...

    JAVA中浮点数的运算

    这篇博客主要探讨了Java中浮点数(包括`float`和`double`类型)运算的特性、存在的问题以及如何应对这些挑战。 首先,Java中的`float`类型占用32位存储空间,它能表示大约6到7位十进制的有效数字,而`double`类型则...

    解决java数值范围以及float与double精度丢失的问题

    解决java数值范围以及float与double精度丢失的问题 Java中的数值范围和浮点数精度问题是许多开发者经常遇到的问题。下面我们将详细探讨Java中的数值范围、float和double类型的精度问题,并且提供解决方案。 一、...

    Java中如何正确进行浮点数运算

    而对于对精度要求不那么高的场景,可以使用`float`或`double`,但需谨慎处理可能出现的精度误差。 总之,理解和掌握Java中的浮点数存储和运算特性,以及如何利用`BigDecimal`进行精确计算,是每个Java开发者必备的...

    Java中实现浮点数的精确计算

    在Java编程中,使用`float`和`double`类型进行浮点数计算时经常会遇到精度丢失的问题。这是因为浮点数在计算机内部是以二进制形式存储的,而某些十进制小数无法用二进制精确表示,从而导致计算结果出现误差。例如,`...

    Java中浮点数精度问题的解决方法

    浮点数精度问题主要体现在,当使用float或double类型的数值进行运算时,结果并不总是与预期相符,这主要是由于计算机内部对浮点数的存储方式导致的。 浮点数在计算机内部是以二进制的科学记数法形式存储的。对于一...

    单精度&双精度浮点数与十六进制数相互转换

    浮点数是一种可以表示小数的数值类型,分为单精度(Single-precision)和双精度(Double-precision)。单精度浮点数占用32位二进制空间,由1位符号位、8位指数位和23位尾数位组成。双精度浮点数则占据64位,包括1位...

    Java源码获取浮点数类型的最大最小值

    在Java编程语言中,浮点数类型包括`float`和`double`,它们分别用于存储单精度和双精度浮点数。了解如何在源码级别获取这两种类型的最大和最小值对于编写高效且精确的代码至关重要。本文将深入探讨Java中获取浮点数...

    16位转浮点型float,MODBUS 32位转浮点型float 64位转双浮点型double

    双浮点型(double)是64位的浮点数,提供更高的精度。同样遵循IEEE 754标准,64位数据由1位符号位、11位指数位和52位尾数组成。转换过程类似于32位转浮点,只是涉及的位数更多,计算也更为复杂。 在编程语言如C、...

    Java 程序将两个浮点数相乘.docx

    `float` 是单精度浮点数,占用 4 字节(32 位),而 `double` 是双精度浮点数,占用 8 字节(64 位)。由于 `double` 比 `float` 更精确,所以在大多数情况下推荐使用 `double`。然而,如果内存限制是一个问题,或者...

    float、double类型介绍.zip

    标题中的“float、double类型介绍”指的是在编程语言中,如C++、Java或Python等,用于表示浮点数的数据类型。浮点数是计算机科学中用来表示小数的一种方式,因为它们不是精确的,而是近似的。浮点类型通常分为两种...

    float和double

    本文将详细解释float和double的范围和精度,及其在商业计算中的应用问题和解决方法。 1. 范围 float和double的范围是由指数的位数来决定的。float的指数位有8位,而double的指数位有11位。因此,float的指数范围为...

    浮点数计算为什么会出错

    浮点数计算错误是计算机科学中的一个经典问题,...总之,理解计算机浮点数表示的原理和它的限制是十分重要的,这可以帮助开发者在编程时更好地处理数值计算,并通过适当的策略来最小化由于浮点数精度限制所引起的误差。

    疯狂Java讲义 浮点数转换成人民币读法

    在Java中,浮点数有两种类型:float和double。float是单精度浮点数,占用4个字节,精度约为7位小数;double是双精度浮点数,占用8个字节,精度约为15位小数。由于浮点数在计算机内部是以二进制形式存储的,因此可能...

    详解java中float与double的区别

    这里有一个小知识:既然 float 和 double 型用来表示带有小数点的数,那为什么我们不称 它们为“小数”或者“实数”,要叫浮点数呢?因为这些数都以科学计数法的形式存储。当一个数如 50.534,转换成科学计数法的...

Global site tag (gtag.js) - Google Analytics