`
gyl868
  • 浏览: 170773 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java金融货币处理

阅读更多
转载
http://imtinx.iteye.com/blog/832325


在《你可能不知道的Java基础知识(一)》中,我提到使用浮点运算要慎重,感觉说的不够透彻,其实float和double类型主要是为科学和工程计算而设计的。他们执行的是二进制浮点运算,由于二进制的局限性,有时候无法得到准确的结果。


例如:System.out.println(2.0-1.1)将输出0.8999999999999999,而不是0.9,当然这在科学计算中无关紧要,通过四舍五入就可以轻松解决问题,但是在禁止出现舍入误差的运算中(比如金融计算)就不适用了。


在二进制中无法精确地表示10的任何负数次方值,比如0.1,这和十进制中无法精确表示1/3一个道理,所以越到像金融货币计算的问题,我们不得不舍弃float和double,而改BigDecimal类。


在《Effective Java》这本书中也提到这个原则,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用java.math.BigDecimal,而且非要用String来够造BigDecimal不可!在《Effective Java》一书中的例子是用String来够造BigDecimal的,但是书上却没有强调这一点,这也许是一个小小的失误吧。



用BigDecimal解决上述2.0-1.1问题的代码为:
Java代码  收藏代码

  
 import java.math.*;  
    class BigDecimalTest   
    {  
        public static void main(String[] args)   
        {  
            //使用字符串构造BigDecimal对象  
            BigDecimal a =new BigDecimal("2.0");  
            BigDecimal b = new BigDecimal("1.1");  
            System.out.println(a.subtract(b));  
        }  
    }  
      
    输出:0.9  




假如不用String来构造BigDecimal问题将依旧:
Java代码  收藏代码

   
import java.math.*;  
    class TestB   
    {  
        public static void main(String[] args)   
        {  
            //使用double来构造BigDecimal,问题依旧  
            BigDecimal a = new BigDecimal(2.0);  
            BigDecimal b = new BigDecimal(1.1);  
            System.out.println(a.subtract(b));  
        }  
    }  
    输出 0.899999999999999911182158029987476766109466552734375  



当然BigDecimal也提供了舍入方法,下面是网上淘来的类,完美的解决了这些问题:
Java代码  收藏代码

   
package com.morningstar.bigdecimal;  
      
    import java.math.BigDecimal;  
      
    public class Arithmetic4Double {  
        //默认除法运算精度  
        private static final int DEF_DIV_SCALE = 10;  
         
        //所有方法均用静态方法实现,不允许实例化  
        private Arithmetic4Double() {}  
      
        /** 
         * 实现浮点数的加法运算功能 
         * @param v1 加数1 
         * @param v2 加数2 
         * @return v1+v2的和 
         */  
        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 v1-v2的差 
         */  
        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 v1×v2的积 
         */  
        public static double multi(double v1,double v2) {  
            BigDecimal b1 = new BigDecimal(Double.toString(v1));  
            BigDecimal b2 = new BigDecimal(Double.toString(v2));  
            return b1.multiply(b2).doubleValue();  
        }  
      
        /** 
         * 实现浮点数的除法运算功能 
         * 当发生除不尽的情况时,精确到小数点以后DEF_DIV_SCALE位(默认为10位),后面的位数进行四舍五入。 
         * @param v1 被除数 
         * @param v2 除数 
         * @return v1/v2的商 
         */  
        public static double div(double v1,double v2) {  
         BigDecimal b1 = new BigDecimal(Double.toString(v1));  
            BigDecimal b2 = new BigDecimal(Double.toString(v2));  
            return b1.divide(b2,DEF_DIV_SCALE,BigDecimal.ROUND_HALF_UP).doubleValue();  
        }  
      
        /** 
         * 实现浮点数的除法运算功能 
         * 当发生除不尽的情况时,精确到小数点以后scale位,后面的位数进行四舍五入。 
         * @param v1 被除数 
         * @param v2 除数 
         * @param scale 表示需要精确到小数点以后几位 
         * @return v1/v2的商 
         */  
        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();  
        }  
    }  

 


总结一句话:精确运算要用String构造的BigDecimal,不要用float和double!
分享到:
评论

相关推荐

    如何将数字型转换成货币型

    在编程领域中,数据类型的转换是十分常见的需求之一,尤其是在处理财务数据时,经常会遇到需要将简单的数字(如整数或浮点数)转换为货币格式的需求。本篇文章将详细介绍如何利用Java中的`java.text.DecimalFormat`...

    Joda-Money-用于表示货币金额的Java库

    总结,Joda-Money是Java开发中处理货币数据的得力助手,它提供了精确、灵活且易于使用的API,使得金融计算变得更加简单和可靠。无论是在电子商务系统、财务软件还是银行应用中,Joda-Money都能发挥其价值。

    yua_java_YUA是什么币种_YUA是那种货币_

    在IT行业中,编程语言Java广泛应用于各种领域,包括金融系统的货币转换应用。在这个特定的例子中,我们关注的是一个关于美元(USD)与欧元(EUR)之间进行转换的简单程序。标题"yua_java_YUA是什么币种_YUA是那种...

    基于Java平台的货币交易系统设计源码

    该系统是一款基于Java平台的货币交易系统,包含79个Java源文件、50个XML配置文件、6个YAML文件以及其他相关文件,共计144个文件,旨在提供一个完整的交易处理解决方案。

    货币汇率转换界面

    在IT行业中,货币汇率转换是一项常见的任务,尤其在金融软件和电子商务平台中。这个"货币汇率转换界面"可能是一个简单的程序或应用,旨在帮助用户计算不同国家货币之间的兑换价值。让我们深入探讨一下这个主题涉及的...

    CurrencyConverter:用Java编写的货币转换器

    【CurrencyConverter:用Java编写的货币转换器】 在IT领域,尤其是软件开发中,货币转换器是一个常见的实用程序,它允许用户将一种货币的价值转换为另一种货币。本项目"CurrencyConverter"是用Java编程语言实现的,...

    MoneyConversion:java中的简单货币转换

    在Java编程语言中,处理货币转换是一个常见的任务,特别是在全球化应用程序中。`MoneyConversion`项目就是一个专注于这个主题的例子。在这个项目中,我们看到如何利用Java的特性来实现一个简单的货币兑换功能,同时...

    java处理大数

    1. **金融系统**:处理货币金额时,由于涉及大量资金,使用`BigInteger`可以避免精度损失问题。 2. **加密算法**:许多加密算法(如RSA)需要处理非常大的数字,此时`BigInteger`就显得尤为重要。 3. **科学计算**:...

    javamoney-lib:JavaMoney金融库,扩展和补充了JSR 354

    尽管JSR 354 API和参考实现提供了诸如金额,可自定义货币和互操作性之类的基础知识,但该库添加了其他功能强大的API和SPI,这些API和SPI在JSR开发过程中作为概念证明(括号中的artifactId): 计算(javamoney-calc...

    Java电子钱包管理系统

    Java电子钱包管理系统是一种基于Java技术实现的金融管理软件,它为用户提供了一种便捷的方式来存储、管理和使用数字货币或者虚拟货币。这个系统的核心特点是安全性、稳定性和可扩展性,这些都是Java编程语言的优势...

    Java的数学运算处理类讲解代码(BigDecimal、Math、Random、DecimalFormat类全部操作方法API)

    这个源码资源是一个讲解数学计算处理类的示例项目,旨在帮助开发者理解和使用Java中的数学计算相关类库。该项目包含详细的代码示例和注释,涵盖了以下几个主要的数学计算处理类:BigDecimal、Math、Random和...

    Android 货币转换

    在Android平台上,货币转换是一个常见的应用场景,特别是在电子商务或者金融类应用中。本项目"Android 货币转换"提供了一个简单但实用的解决方案,主要针对欧元(EUR)和美元(USD)之间的转换。这个项目是使用...

    java人民币处理

    在Java编程语言中,处理人民币金额的转换是一个常见的需求,尤其是在金融、会计或者任何涉及到货币操作的系统中。本文将深入解析一个简单的Java类——`RMB`,它专门用于将整数形式的人民币金额转换为汉字大写形式,...

    java金钱处理方法实例详解

    在Java编程中,处理金钱数据是一项关键任务,尤其是在金融、电商等涉及交易的领域。由于金钱涉及精度问题,直接使用基本类型如int或double可能会导致精度丢失,因此需要采用特定的方式来处理。本篇将深入讲解Java中...

    webservice调用天气预报、各国货币转换的核心代码

    7. **货币转换代码**:类似的,这部分代码会构建另一个SOAP请求,调用货币转换服务,接收并处理返回的货币汇率信息。可能涉及到了金融API的使用,如Open Exchange Rates或其它第三方服务。 8. **集成与部署**:这些...

    Rmb.rar_人民币 转换 java_人民币大写

    这个"Rmb.rar_人民币 转换 java_人民币大写"的压缩包就是一个典型的例子,它包含了一个Java程序,用于将数字转换成符合中国金融规范的人民币大写形式。这种转换对于财务报表、发票开具等场景至关重要,因为它们要求...

    java图形界面实现的至少三种以上汇率转换

    - 货币汇率是两种货币之间的交换比率,通常由中央银行或金融市场决定。 - 实时汇率:需要通过网络调用API获取最新汇率数据。例如,Open Exchange Rates提供免费API,可以获取到实时的汇率信息。 3. **API接口使用...

    JAVA_大数操作

    在实际编程中,`BigInteger`常用于加密算法、高精度计算、金融领域的货币计算等场景,其中精确性和大数支持是必不可少的。通过学习和掌握`BigInteger`类,开发者可以处理Java标准整数类型无法胜任的计算任务。 总结...

    动态获取汇率资料

    在IT行业中,动态获取汇率资料是一项常见的需求,特别是在金融、电商等领域。为了满足这一需求,开发者经常使用外部API,如Google提供的汇率转换API。本文将详细介绍如何利用API来动态获取并处理汇率信息,并探讨...

Global site tag (gtag.js) - Google Analytics