Java 避免精度丢失之BigDecimal 运算

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

/** 计算工具类
*/
public class Arith {

    /** 加
     * 提供精确的加法运算。
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double add(double v1, double v2) {

        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    /** 减
     * 提供精确的减法运算。
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static double sub(double v1, double v2) {

        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    /** 乘
     * 提供精确的乘法运算。
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static double mul(double v1, double v2) {

        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

    /** 除
     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
     * 定精度,以后的数字四舍五入。
     * @param v1 被除数
     * @param v2 除数
     * @param scale 表示表示需要精确到小数点以后几位,避免精度丢失。
     * @return 两个参数的商
     */
    public static double div(double v1, double v2, int scale) {

        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 提供精确的小数位四舍五入处理。
     * @param v 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v, int scale) {

        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");  //除数
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }
};
时间: 2024-10-12 08:17:49

Java 避免精度丢失之BigDecimal 运算的相关文章

Java 浮点数精度丢失

Java 浮点数精度丢失 问题引入 昨天帮室友写一个模拟发红包抢红包的程序时,对金额统一使用的 double 来建模,结果发现在实际运行时程序的结果在数值上总是有细微的误差,程序运行的截图: 输入依次为:红包个数,抢红包的人数,选择固定金额红包还是随机金额红包,每个红包的金额(此例只有一个红包). 注意到程序最后的结果是有问题的,我们只有一个金额为 10 的红包,一个人去抢,所以正确结果应该为这个人抢到了 10 RMB. 为了使问题更加明显,我们测试一个更加简单的例子: public class

关于Java中用Double型运算时精度丢失的问题

注:转自 https://blog.csdn.net/bleach_kids/article/details/49129943 在使用Java,double 进行运算时,经常出现精度丢失的问题,总是在一个正确的结果左右偏0.0000**1. 特别在实际项目中,通过一个公式校验该值是否大于0,如果大于0我们会做一件事情,小于0我们又处理其他事情. 这样的情况通过double计算出来的结果去和0比较大小,尤其是有小数点的时候,经常会因为精度丢失而导致程序处理流程出错. BigDecimal在<Eff

Java Float类型 减法运算时精度丢失问题

package test1; public class Test2 { /*** @param args*/public static void main(String[] args) {   Float xx = 2.0f;   Float yy = 1.8f;   Float tt = xx - yy;   System.out.println("tttttt-----" + tt); } } 果然输出结果是: tttttt-----0.20000005 再测试了几个float类型

java中两double相加精度丢失问题及解决方法

在讨论两位double数0.1和0.2相加时,毫无疑问他们相加的结果是0.2.但是问题总是如此吗? 下面我们让下面两个doubles数相加,然后看看输出结果: @Test public void testBig(){ System.out.println(0.11+2001299.32); } 控制台输出2001299.4300000002 我们吃惊的发现,结果并不是我们预想的那样,这是为什么呢?又如何解决呢? 现贴出BigDecimal的一个构造函数的文档供大家参考 BigDecimal pu

【转】JAVA程序中Float和Double精度丢失问题

原文网址:http://blog.sina.com.cn/s/blog_827d041701017ctm.html 问题提出:12.0f-11.9f=0.10000038,"减不尽"为什么? 来自MSDN的解释: http://msdn.microsoft.com/zh-cn/c151dt3s.aspx 为何浮点数可能丢失精度浮点十进制值通常没有完全相同的二进制表示形式. 这是 CPU 所采用的浮点数据表示形式的副作用.为此,可能会经历一些精度丢失,并且一些浮点运算可能会产生意外的结果

浮点数的运算精度丢失

引出 打开Python编译器,输入 0.1+0.2, 期待的结果是0.3,但是输出为: 0.30000000000000004 有点小尴尬,这是为什么呢? 解惑 其实这设计到了计算机的浮点数存储是以二进制进行存储的. 说二进制不太形象,换成我们最长使用的十进制和分数 1/5,使用小数表示为0.2,但是1/3,使用小数表示就是一个无限循环小数:0.3333333, 也就是说,分数的 1/3+1/3=2/3,但如果使用小数:0.3333+0.3333=0.6666, 结果只会无限接近2/3,而不会等

关于JavaScript中计算精度丢失的问题

摘要: 由于计算机是用二进制来存储和处理数字,不能精确表示浮点数,而JavaScript中没有相应的封装类来处理浮点数运算,直接计算会导致运算精度丢失. 为了避免产生精度差异,把需要计算的数字升级(乘以10的n次幂)成计算机能够精确识别的整数,等计算完毕再降级(除以10的n次幂),这是大部分编程语言处理精度差异的通用方法. 关键词: 计算精度 四舍五入 四则运算 精度丢失 1. 疑惑 我们知道,几乎每种编程语言都提供了适合货币计算的类.例如C#提供了decimal,Java提供了BigDecim

经典的精度丢失问题

Java中的类型float.double用来做计算会有精度丢失问题,下面来看下面的示例. public static void main(String[] args) {    test1();    test2(); } private static void test1() {    double totalAmount = 0.09;    double feeAmount = 0.02;    double tradeAmount = totalAmount - feeAmount;  

【解惑】剖析float型的内存存储和精度丢失问题

问题提出:12.0f-11.9f=0.10000038,"减不尽"为什么? 现在我们就详细剖析一下浮点型运算为什么会造成精度丢失? 1.小数的二进制表示问题 首先我们要搞清楚下面两个问题: (1)  十进制整数如何转化为二进制数 算法很简单.举个例子,11表示成二进制数: 11/2=5   余   1 5/2=2   余   1 2/2=1   余   0 1/2=0   余   1 0结束         11二进制表示为(从下往上):1011 这里提一点:只要遇到除以后的结果为0了