转载
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开发中处理货币数据的得力助手,它提供了精确、灵活且易于使用的API,使得金融计算变得更加简单和可靠。无论是在电子商务系统、财务软件还是银行应用中,Joda-Money都能发挥其价值。
在IT行业中,编程语言Java广泛应用于各种领域,包括金融系统的货币转换应用。在这个特定的例子中,我们关注的是一个关于美元(USD)与欧元(EUR)之间进行转换的简单程序。标题"yua_java_YUA是什么币种_YUA是那种...
该系统是一款基于Java平台的货币交易系统,包含79个Java源文件、50个XML配置文件、6个YAML文件以及其他相关文件,共计144个文件,旨在提供一个完整的交易处理解决方案。
在IT行业中,货币汇率转换是一项常见的任务,尤其在金融软件和电子商务平台中。这个"货币汇率转换界面"可能是一个简单的程序或应用,旨在帮助用户计算不同国家货币之间的兑换价值。让我们深入探讨一下这个主题涉及的...
【CurrencyConverter:用Java编写的货币转换器】 在IT领域,尤其是软件开发中,货币转换器是一个常见的实用程序,它允许用户将一种货币的价值转换为另一种货币。本项目"CurrencyConverter"是用Java编程语言实现的,...
在Java编程语言中,处理货币转换是一个常见的任务,特别是在全球化应用程序中。`MoneyConversion`项目就是一个专注于这个主题的例子。在这个项目中,我们看到如何利用Java的特性来实现一个简单的货币兑换功能,同时...
1. **金融系统**:处理货币金额时,由于涉及大量资金,使用`BigInteger`可以避免精度损失问题。 2. **加密算法**:许多加密算法(如RSA)需要处理非常大的数字,此时`BigInteger`就显得尤为重要。 3. **科学计算**:...
尽管JSR 354 API和参考实现提供了诸如金额,可自定义货币和互操作性之类的基础知识,但该库添加了其他功能强大的API和SPI,这些API和SPI在JSR开发过程中作为概念证明(括号中的artifactId): 计算(javamoney-calc...
Java电子钱包管理系统是一种基于Java技术实现的金融管理软件,它为用户提供了一种便捷的方式来存储、管理和使用数字货币或者虚拟货币。这个系统的核心特点是安全性、稳定性和可扩展性,这些都是Java编程语言的优势...
这个源码资源是一个讲解数学计算处理类的示例项目,旨在帮助开发者理解和使用Java中的数学计算相关类库。该项目包含详细的代码示例和注释,涵盖了以下几个主要的数学计算处理类:BigDecimal、Math、Random和...
在Android平台上,货币转换是一个常见的应用场景,特别是在电子商务或者金融类应用中。本项目"Android 货币转换"提供了一个简单但实用的解决方案,主要针对欧元(EUR)和美元(USD)之间的转换。这个项目是使用...
在Java编程语言中,处理人民币金额的转换是一个常见的需求,尤其是在金融、会计或者任何涉及到货币操作的系统中。本文将深入解析一个简单的Java类——`RMB`,它专门用于将整数形式的人民币金额转换为汉字大写形式,...
在Java编程中,处理金钱数据是一项关键任务,尤其是在金融、电商等涉及交易的领域。由于金钱涉及精度问题,直接使用基本类型如int或double可能会导致精度丢失,因此需要采用特定的方式来处理。本篇将深入讲解Java中...
7. **货币转换代码**:类似的,这部分代码会构建另一个SOAP请求,调用货币转换服务,接收并处理返回的货币汇率信息。可能涉及到了金融API的使用,如Open Exchange Rates或其它第三方服务。 8. **集成与部署**:这些...
这个"Rmb.rar_人民币 转换 java_人民币大写"的压缩包就是一个典型的例子,它包含了一个Java程序,用于将数字转换成符合中国金融规范的人民币大写形式。这种转换对于财务报表、发票开具等场景至关重要,因为它们要求...
- 货币汇率是两种货币之间的交换比率,通常由中央银行或金融市场决定。 - 实时汇率:需要通过网络调用API获取最新汇率数据。例如,Open Exchange Rates提供免费API,可以获取到实时的汇率信息。 3. **API接口使用...
在实际编程中,`BigInteger`常用于加密算法、高精度计算、金融领域的货币计算等场景,其中精确性和大数支持是必不可少的。通过学习和掌握`BigInteger`类,开发者可以处理Java标准整数类型无法胜任的计算任务。 总结...
在IT行业中,动态获取汇率资料是一项常见的需求,特别是在金融、电商等领域。为了满足这一需求,开发者经常使用外部API,如Google提供的汇率转换API。本文将详细介绍如何利用API来动态获取并处理汇率信息,并探讨...