bigdecimal精度问题(什么时候double精度出现问题,可以用BigDecimal代替)

本文目录
- 什么时候double精度出现问题,可以用BigDecimal代替
- 如何处理浮点数的精度问题
- BigDecimal 精度 和准确度问题
- Java 中 double 类数据运算精度不准怎么解决
- resultset getbigdecimal 出来的数会有精度问题吗
- BigDecimal的精度问题!
什么时候double精度出现问题,可以用BigDecimal代替
看看计算机基础吧
用double计算会造成精度丢失的,而float不会出现这种情况的原因是由于它在计算机种的表示
方式是科学表示法。
如果不懂科学表示法,可以去google搜索下。
一般解决double出现精度问题的方法,是使用BigDecimal来代替Double计算,银行系统的数据计算都是采用BigDecimal。
如果不知道BigDecimal可以goole一下,了解一下
我只告诉了你的解决方法,具体怎么解决你自己看着办,通过解决这些问题,可以提高你解决问题的能力以及你对搜索引擎的使用。这些能力是技术人员必须的
如何处理浮点数的精度问题
您好,很高兴为您解答。
一般对double类型进行运算时,做好对结果进行处理,然后拿这个值去做其他事情。 下面我们就用代码来说明一下如何对浮点数进行精度计算,以double为例。
* Copyright reserved 2010 by AllensLab
* @project AllensLab
* @date Feb 22, 2010
*/
package cn.allen.tools;
import java.math.BigDecimal;
/**
* RoundTool
* @author allen
* @time 10:05:40 AM Feb 22, 2010
*/
public class RoundTools {
/**
* 对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;
}
public static BigDecimal roundAgain(double value, int scale, int roundingMode) {
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(scale, roundingMode);
return bd;
}
/* 用于加、减、乘和除的方法给 BigDecimal 值提供了算术运算。由于 BigDecimal 对象是不可变的,这些方法中的每一个都会产生新的 BigDecimal 对象。
* 因为创建对象的开销, BigDecimal 不适合于大量的数学计算,但设计它的目的是用来精确地表示小数。 */
/**
* Addition
* @param number1
* @param number2
* @return
* @author allen
* @date 10:42:47 AM Feb 22, 2010
*/
public static double add(double number1, double number2, int newScale, int roundingMode) {
return BigDecimal.valueOf(number1).add(BigDecimal.valueOf(number2)).setScale(newScale, roundingMode).doubleValue();
}
public static double add(int newScale, int roundingMode, double number1, double numbers) {
BigDecimal bd = new BigDecimal(number1);
for (double number : numbers) {
bd = bd.add(BigDecimal.valueOf(number).setScale(newScale, roundingMode));
}
return bd.doubleValue();
}
/**
* Subtraction
* @param number1
* @param number2
* @return
* @author allen
* @date 10:45:36 AM Feb 22, 2010
*/
public static double subtract(double number1, double number2, int newScale, int roundingMode) {
return BigDecimal.valueOf(number1).subtract(BigDecimal.valueOf(number2)).setScale(newScale, roundingMode).doubleValue();
}
/**
* Multiplication
* @param number1
* @param number2
* @return
* @author allen
* @date 10:46:23 AM Feb 22, 2010
*/
public static double multiply(double number1, double number2, int newScale, int roundingMode) {
return BigDecimal.valueOf(number1).multiply(BigDecimal.valueOf(number2)).setScale(newScale, roundingMode).doubleValue();
}
/**
* Division
* 尽量采用财务常用的四舍六入五取偶 即ROUND_HALF_EVEN
* @param number1
* @param number2
* @return
* @author allen
* @date 10:47:12 AM Feb 22, 2010
*/
public static double divide(double number1, double number2, int scale, int roundingMode) {
return BigDecimal.valueOf(number1).divide(BigDecimal.valueOf(number2), scale, roundingMode).doubleValue();
}
/**
* 测试用的main方法.
*
* @param args
* 运行参数.
*/
public static void main(String args) {
//下面都以保留2位小数为例
System.out.println(add(12.341, 12.3449, 2, BigDecimal.ROUND_HALF_EVEN));
System.out.println(add(2, BigDecimal.ROUND_HALF_UP, 12.346, 12.3449, 12.3401, 12.345));
System.out.println(subtract(12.3449, 12.341, 2, BigDecimal.ROUND_HALF_EVEN));
System.out.println(multiply(12.3449, 0.01, 2, BigDecimal.ROUND_HALF_UP));
System.out.println(divide(11.341, 12.346, 2, BigDecimal.ROUND_HALF_EVEN));
//ROUND_UP
//只要第2位后面存在大于0的小数,则第2位就+1
System.out.println(“-- 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_DOWN -- 直接舍弃第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(“-- OUND_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_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_HALF_UP -- 如果第3位数字》=5,则第2位数字+1 --“);
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_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_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
}
}
如若满意,请点击右侧【采纳答案】,如若还有问题,请点击【追问】
希望我的回答对您有所帮助,望采纳!
~ O(∩_∩)O~
BigDecimal 精度 和准确度问题
Api写的很清楚:
public class BigDecimalextends Numberimplements Comparable《BigDecimal》
不可变的、任意精度的有符号十进制数。BigDecimal 由任意精度的整数非标度值 和 32 位的整数标度
(scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负 scale
次幂。因此,BigDecimal 表示的数值是 (unscaledValue × 10-scale)。
BigDecimal 类提供以下操作:算术、标度操作、舍入、比较、哈希算法和格式转换。toString()
方法提供 BigDecimal 的规范表示形式。
BigDecimal 类使用户能完全控制舍入行为。如果未指定舍入模式,并且无法表示准确结果,则抛出一个异常;否则,通过向该操作提供适当的
MathContext
对象,可以对已选择的精度和舍入模式执行计算。在任何情况下,可以为舍入控制提供八种舍入模式。使用此类(例如,ROUND_HALF_UP)中的整数字段来表示舍入模式已过时;应改为使用
RoundingModeenum(例如,RoundingMode.HALF_UP)的枚举值。
当为 MathContext 对象提供 0 的精度设置(例如,MathContext.UNLIMITED)时,算术运算是准确的,它们是不采用任何
MathContext 对象的算术方法。(这是第 5 版之前的版本支持的惟一行为。)为了计算准确结果,不使用附带 0 精度设置的
MathContext 对象的舍入模式设置,因此与该对象无关。在除法中,准确的商可能是一个无限长的十进制扩展;例如,1 除以 3
所得的商。如果商具有无穷的十进制扩展,但是指定了该操作返回准确结果,则抛出
ArithmeticException。否则,像其他操作那样,返回除法运算的准确结果。
当精度设置不为 0 时,BigDecimal 算法的规则完全符合 ANSI X3.274-1996 和 ANSI
X3.274-1996/AM 1-2000( 7.4 节)中定义的算法的可选操作模式。与上述标准不同,BigDecimal
包括多种舍入模式,它们对于版本 5 以前的 BigDecimal 版本中的除法是强制性的。这些 ANSI 标准和
BigDecimal 规范之间的任何冲突都按照有利于 BigDecimal 的方式进行解决。
由于同一数值可以有不同的表示形式(具有不同的标度),因此运算和舍入的规则必须同时指定数值结果和结果表示形式中所用的标度。
一般情况下,当准确结果(在除法中,可能有无限多位)比返回的数值具有更多位数时,舍入模式和精度设置确定操作如何返回具有有限位数的结果。
首先,MathContext 的 precision
设置指定要返回的总位数;这确定了结果的精度。位数计数从准确结果的最左边的非零数字开始。舍入模式确定丢弃的尾部位数如何影响返回的结果。
对于所有算术运算符,运算的执行方式是,首先计算准确的中间结果,然后,使用选择的舍入模式将其舍入为精度设置(如有必要)指定的位数。如果不返回准确结果,则将丢弃准确结果的某些数位。当舍入增加了返回结果的大小时,前导数字“9”的进位传播可能会创建新的数位。例如,将值
999.9 舍入为三位数字,则在数值上等于一千,表示为 100×101。在这种情况下,新的 “1“ 是返回结果的前导数位。
除了逻辑的准确结果外,每种算术运算都有一个表示结果的首选标度。下表列出了每个运算的首选标度。
算术运算结果的首选标度
运算结果的首选标度
加 max(addend.scale(), augend.scale())
减 max(minuend.scale(), subtrahend.scale())
乘 multiplier.scale() + multiplicand.scale()
除 dividend.scale() -
divisor.scale()
这些标度是返回准确算术结果的方法使用的标度;准确相除可能必须使用较大的标度除外,因为准确的结果可能有较多的位数。例如,1/32
得到 0.03125。
舍入之前,逻辑的准确中间结果的标度是该运算的首选标度。如果用 precision
位数无法表示准确的数值结果,则舍入会选择要返回的一组数字,并将该结果的标度从中间结果的标度减小到可以表示实际返回的 precision
位数的最小标度。如果准确结果可以使用最多 precision
个数字表示,则返回具有最接近首选标度的标度的结果表示形式。尤其是,通过移除结尾零并减少标度,可以用少于 precision
个数字来表示准确的可表示的商。例如,使用 floor
舍入模式将结果舍入为三个数字,
19/100 = 0.19 // integer=19, scale=2
但是
21/110 = 0.190 // integer=190, scale=3
注意,对于加、减和乘,标度的缩减量将等于丢弃的准确结果的数字位置数。如果舍入导致进位传播创建一个新的高位,则当未创建新的数位时,会丢弃该结果的附加数字。
其他方法可能与舍入语义稍微不同。例如,使用指定的算法的
pow 方法得到的结果可能偶尔不同于舍入得到的算术结果,如最后一位有多个单位(ulp)。
可以通过两种类型的操作来处理 BigDecimal 的标度:标度/舍入操作和小数点移动操作。标度/舍入操作(setScale
和 round)返回
BigDecimal,其值近似地(或精确地)等于操作数的值,但是其标度或精度是指定的值;即:它们会增加或减少对其值具有最小影响的存储数的精度。小数点移动操作(movePointLeft
和 movePointRight)返回从操作数创建的
BigDecimal,创建的方法是按指定方向将小数点移动一个指定距离。
为了简洁明了起见,整个 BigDecimal 方法的描述中都使用了伪代码。伪代码表达式 (i + j) 是“其值为
BigDecimali 加 BigDecimalj 的
BigDecimal”的简写。伪代码表达式 (i == j) 是“当且仅当 BigDecimali 表示与 BigDecimalj 相同的值时,则为
true”的简写。可以类似地解释其他伪代码表达式。方括号用于表示特定的 BigInteger 和定义
BigDecimal 值的标度对;例如,[19, 2] 表示 BigDecimal 在数值上等于 0.19,标度是 2。
注:如果 BigDecimal 对象用作 SortedMap 中的键或 SortedSet 中的元素,则应特别小心,因为
BigDecimal 的自然排序与 equals 方法不一致。有关更多信息,请参见 Comparable、SortedMap 或 SortedSet。
当为任何输入参数传递 null 对象引用时,此类的所有方法和构造方法都将抛出
NullPointerException。
Java 中 double 类数据运算精度不准怎么解决
在大多数情况下,使用double和float计算的结果是准确的,但是在一些精度要求很高的系统中,这种问题是非常严重的。在《Effective Java》中提到一个原则,那就是float和double只能用来作科学计算或者是工程计算,但在商业计算中我们要用java.math.BigDecimal,通过使用BigDecimal类可以解决上述问题,实例代码如下:《pre t=“code“ l=“java“》package ex;
import java.math.*;
public class BigDecimalDemo {
public static void main(String args){
System.out.println(ArithUtil.add(0.01, 0.05));
System.out.println(ArithUtil.sub(1.0, 0.42));
System.out.println(ArithUtil.mul(4.015, 100));
System.out.println(ArithUtil.div(123.3, 100));
}
}
class ArithUtil{
private static final int DEF_DIV_SCALE=10;
private ArithUtil(){}
//相加
public static double add(double d1,double d2){
BigDecimal b1=new BigDecimal(Double.toString(d1));
BigDecimal b2=new BigDecimal(Double.toString(d2));
return b1.add(b2).doubleValue();
}
//相减
public static double sub(double d1,double d2){
BigDecimal b1=new BigDecimal(Double.toString(d1));
BigDecimal b2=new BigDecimal(Double.toString(d2));
return b1.subtract(b2).doubleValue();
}
//相乘
public static double mul(double d1,double d2){
BigDecimal b1=new BigDecimal(Double.toString(d1));
BigDecimal b2=new BigDecimal(Double.toString(d2));
return b1.multiply(b2).doubleValue();
}
//相除
public static double div(double d1,double d2){
return div(d1,d2,DEF_DIV_SCALE);
}
public static double div(double d1,double d2,int scale){
if(scale《0){
throw new IllegalArgumentException(“The scale must be a positive integer or zero“);
}
BigDecimal b1=new BigDecimal(Double.toString(d1));
BigDecimal b2=new BigDecimal(Double.toString(d2));
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
resultset getbigdecimal 出来的数会有精度问题吗
看看计算机基础吧 用double计算会造成精度丢失的,而float不会出现这种情况的原因是由于它在计算机种的表示 方式是科学表示法。 如果不懂科学表示法,可以去google搜索下。 一般解决double出现精度问题的方法,是使用BigDecimal来代替Double
BigDecimal的精度问题!
public static void main(String args){
BigDecimal i=new BigDecimal(13);
BigDecimal x=new BigDecimal(0.85);
java.text.DecimalFormat df=new java.text.DecimalFormat(“0.00“); //格式化,保留两位小数
System.out.println(“i.multiply(x)=“+i.multiply(x));
System.out.println(“i.multiply(x)=“+df.format(i.multiply(x)));
}
结果是:
i.multiply(x)=11.04999999999999971134201359745929948985576629638671875
i.multiply(x)=11.05

更多文章:
dropdownlist 绑定(DropDownList 绑定所有项 并 显示指定项)
2026年10月11日 08:50
易语言网页api接口怎么调用(易语言,怎么读取网页json的api)
2026年10月11日 08:00
majority of(the majority of 和 a majority of的区别以及用法例句)
2026年10月11日 07:40
another time(another time和other time的区别)
2026年10月11日 05:00






