java中金额(浮点表示)的计算
来源:互联网 发布:大数据培训班 编辑:程序博客网 时间:2024/06/05 16:37
java中进行金额的计算经常浮点数丢失精度,造成这种问题的原因应该与cpu对浮点数的计算方式有关,有下面的介绍:
从原理上来讲,任何一门语言对于浮点数的计算都是不精确的。
因为现在的Computer都是基于二进制数来存储计算的。
例如计算8+3时,Computer会转换为二进制的加法1000+11=1011,然后再转换为十进制数为11。
这种算法对于整数来说是不会产生误差的(如果不超过计算范围);
而对于浮点数计算有时就会产生误差。因为有的浮点数转换成为二进制时是一个无穷循环小数。
例如十进制的0.4,转换成为二进制为0.0110011001100110....,这样,在0.4+0.3时就不能准确的算出是0.7,
而是经过一些舍入处理才能得出正确结果,但经过多次运算误差产生的较大时,
即使经过一些舍入处理也不能得到精确的结果了。
既然这样,那么在java中为了保持精度需要怎样做呢?
一句话:用BigDecimal进行运算;BigDecimal的构造函数有下面几种:
BigDecimal(BigInteger val)
Translates a BigInteger into a BigDecimal.
BigDecimal(BigInteger unscaledVal, int scale)
Translates a BigInteger unscaled value and an int scale into a BigDecimal.
BigDecimal(double val)
Translates a double into a BigDecimal.
BigDecimal(String val)
Translates the String representation of a BigDecimal into a BigDecimal.
按照jdk帮助文档说明,如果采用double类型构造函数的话有可能丢失精度,推荐采用String类型的构造函数.
Note: the results of this constructor can be somewhat unpredictable.
One might assume that new BigDecimal(.1) is exactly equal to .1, but it is actually equal to
.1000000000000000055511151231257827021181583404541015625. This is so because .1 cannot be represented
exactly as a double (or, for that matter, as a binary fraction of any finite length).
Thus, the long value that is being passed in to the constructor is not exactly equal to .1,
appearances notwithstanding.
在用的过程中写了一个帮助类Amount,以解决在日常开发中遇到的金额计算问题:
import java.io.Serializable;
import java.math.BigDecimal;
/** *//**
* 金额类型. 支持自身的四则运算,并将this返回.
*/
public class Amount implements Serializable ...{
private BigDecimal value;
/** *//**
* 提供默认精度10
*/
private int scale = 10;
/** *//**
* double类型构造函数
*
* @param value
*/
public Amount(double value) ...{
this.value = new BigDecimal(Double.toString(value));
}
/** *//**
* String类型构造函数
*
* @param value
*/
public Amount(String value) ...{
this.value = new BigDecimal(value);
}
/** *//**
* 取得BigDecimal的值
*
* @return
*/
public BigDecimal getValue() ...{
return this.value;
}
/** *//**
* 两个double类型的数值相加
*
* @param v1
* @param v2
* @return
*/
public double add(double v1, double v2) ...{
Amount a1 = new Amount(v1);
Amount a2 = new Amount(v2);
return add(a1, a2);
}
/** *//**
* 两数相除
*
* @param v1
* @param v2
* @return
*/
public double div(double v1, double v2) ...{
Amount a1 = new Amount(v1);
Amount a2 = new Amount(v2);
return this.divide(a1, a2);
}
/** *//**
* 相减
*
* @param v1
* @param v2
* @return
*/
public double sub(double v1, double v2) ...{
Amount a1 = new Amount(v1);
Amount a2 = new Amount(v2);
return this.subtract(a1, a2);
}
/** *//**
* 相乘
*
* @param v1
* @param v2
* @return
*/
public double mul(double v1, double v2) ...{
Amount a1 = new Amount(v1);
Amount a2 = new Amount(v2);
return this.multiply(a1, a2);
}
/** *//**
* 两个Amount类型的数据进行相加
*
* @param v1
* @param v2
* @return
*/
public double add(Amount v1, Amount v2) ...{
return v1.getValue().add(v2.getValue()).doubleValue();
}
/** *//**
* 两个Amount类型变量相除
*
* @param v1
* @param v2
* @return
*/
public double divide(Amount v1, Amount v2) ...{
if (scale < 0) ...{
throw new IllegalArgumentException("精度指定错误,请指定一个>=0的精度");
}
return v1.getValue().divide(v2.getValue(), scale,
BigDecimal.ROUND_HALF_UP).doubleValue();
}
/** *//**
* 两数相乘
*
* @param v1
* @param v2
* @return
*/
public double multiply(Amount v1, Amount v2) ...{
return v1.getValue().multiply(v2.getValue()).doubleValue();
}
/** *//**
* 两数相减
*
* @param v1
* @param v2
* @return
*/
public double subtract(Amount v1, Amount v2) ...{
return v1.getValue().subtract(v2.getValue()).doubleValue();
}
/** *//**
* 返回value的浮点数值
*
* @return
*/
public double doubleValue() ...{
return this.getValue().doubleValue();
}
/** *//**
* 设置精度
* @param scale
*/
public void setScale(int scale) ...{
this.scale = scale;
}
}
- java中金额(浮点表示)的计算
- java中金额(浮点表示)的计算
- Java中浮点数的正确表示
- 商业应用中Java浮点数的精确计算及表示
- 商业应用中Java浮点数的精确计算及表示
- 商业应用中Java浮点数的精确计算及表示
- 商业应用中Java浮点数的精确计算及表示
- 商业应用中Java浮点数的精确计算及表示
- 商业应用中Java浮点数的精确计算及表示
- 商业应用中Java浮点数的精确计算及表示
- Java浮点数的精确计算及表示
- Java浮点数的精确计算及表示
- Java浮点数的精确计算及表示
- Java浮点数的精确计算及表示
- Java浮点数的精确计算及表示
- Java浮点数的精确计算及表示
- 剖析金额不能用浮点数表示的原因
- 剖析金额不能用浮点数表示的原因
- List
- 用1、2、2、3、4、5这六个数字,用java写一个main函数,打印出所有不同的排列, 如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连.
- 过年之惑
- 处理ora-00312的错误(磁盘空间导致00312错误)
- 开发自己的SQL2005报表查看SharePoint WebPart(一)
- java中金额(浮点表示)的计算
- javascript入门·表单和表单元素二 (文本相关,按钮,单、复选按钮) .txt
- 更改Windows XP序列号的工具KeyFinder
- 使用VIM开发软件项目 - (3) vimrc初步
- javascript入门·向函数传递表单数据和元素(赠送一小技巧) .txt
- javascript入门系列演示·函数的定义以及简单参数使用,调用函数 .txt
- javascript入门系列演示·三种弹出对话框的用法实例 .txt
- js入门·表单详解一(修改表单属性,修改表单元素值) .txt
- VC++中进程间相互通信的多种方法