bigdecimal除法精度(请问各位大侠,想实现double保留5位小数,不四舍五入,应该怎么实现)
本文目录
- 请问各位大侠,想实现double保留5位小数,不四舍五入,应该怎么实现
- bigdecimal加减乘除运算顺序
- BigDecimal 精度 和准确度问题
- java,浮点数运算无法精确怎么办
- bigdecimal除以10000可以保留精度吗
- double计算结果不精确
请问各位大侠,想实现double保留5位小数,不四舍五入,应该怎么实现
package big_decimal;
import java.math.BigDecimal;
public class Arith {
// 默认除法运算精度
private static final int DEF_DIV_SCALE = 10;
// 这个类不能实例化
private 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();
}
/** */
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
*
* @param v1
* 被除数
* @param v2
* 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return div(v1, v2, DEF_DIV_SCALE);
}
/** */
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由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();
}
public static void main(String args) {
double num1 = 10.0D;
double num2 = 6.0D;
double num = Arith.div(num1, num2);
String str = num + "";
System.out.println(num);
if (str.split("\\.").length() 》= 5) {
System.out.println(str.split("\\.").substring(0, 5));
} else {
System.out.println(num);
}
}
}
bigdecimal加减乘除运算顺序
bigdecimal加减乘除运算顺序如下:
首先是bigdecimal的初始化,加法 add()函数、减法subtract()函数、乘法multiply()函数、除法divide()函数、绝对值abs()函数。
注意:
1)System.out.println()中的数字默认是double类型的,double类型小数计算不精准。
2)使用BigDecimal类构造方法传入double类型时,计算的结果也是不精确的!
因为不是所有的浮点数都能够被精确的表示成一个double 类型值,有些浮点数值不能够被精确的表示成 double 类型值,因此它会被表示成与它最接近的 double 类型的值。必须改用传入String的构造方法。
除法divide()参数使用;
使用除法函数在divide的时候要设置各种参数,要精确的小数位数和舍入模式,不然会出现报错。
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。
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 值的标度对;例如, 表示 BigDecimal 在数值上等于 0.19,标度是 2。
注:如果 BigDecimal 对象用作 SortedMap 中的键或 SortedSet 中的元素,则应特别小心,因为
BigDecimal 的自然排序与 equals 方法不一致。有关更多信息,请参见 Comparable、SortedMap 或 SortedSet。
当为任何输入参数传递 null 对象引用时,此类的所有方法和构造方法都将抛出
NullPointerException。
java,浮点数运算无法精确怎么办
double表示浮点数时是有精度限制的,这跟double计算机内部的表示有关,任意一个double都要变成 尾码*2^阶码,且1《=尾码《2,如 1.45*2^5,1.45存储时只存小数点后面的数,0.45最后也变成2^b0+2^b1+2^bn,尾码存储时每一位就是b0,b1,...bn,0.4无法精确表示的。
如果想使用无精度限制,那就只能使用BigDecimal
BigDecimal dec = new BigDecimal("123456789.06"); //这个就是精确的123456789.06
BigDecimal dec1 = new BigDecimal("1000.40");
BigDecimal dec2 = new BigDecimal("1000");
BigDecimal dec3 = dec1.subtract(dec2); //这个就是精确的0.4
bigdecimal除以10000可以保留精度吗
bigdecimal除以10000可以保留精度。根据查询相关公开信息显示:如果是float或double类型转Bigdecimal,不要使用newBigDecimal()转,使用valueOf()方法或newBigDecimal()转成string,否则有可能出现精度问题。
double计算结果不精确
问题场景:
使用double进行计算时,偶尔会出现计算不准确的现象,比如:398649.9+0.2 = 398650.10000000003
问题原因:
计算机计算的时候数字是用二进制保存的,计算后再转换成十进制,如果精度不够就会出现误差。
解决办法:
decimal是128位高精度浮点数,常用于金融运算,不会出现浮点数计算的误差。
如果项目对执行效率要求高就使用double,如果项目对数字精确度要求高就使用decimal类型(java语言使用BigDecimal)。
BigDecimal的构造函数入参为String类型,分别使用add、subtract、multiply、divide直接进行加减乘除运算,也可以指定运算结果精确到小数点后几位。
1)直接进行加法
public static String add(String v1,String v2){
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.add(b2).toString();
}
2)指定精确位数的除法
public static String div(String v1,String v2,int scale){
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).toString();
}
备注:
js中可以将浮点数转为整数,再对结果做运算。比如0.1 + 0.2,可以转化为(1*2)/3
js四舍五入使用toFixed()方法
js判断两位小数输入的正则表达式为RegExp("^({0,2})?$");
更多文章:
美食网站是什么(美国有哪些美食网站,类型于下厨房,豆果网的)
2026年3月29日 00:20
会话层是osi模型的第几层(在osi参考模型的分层结构中会话层属第几层)
2026年3月28日 23:40
bigdecimal除法精度(请问各位大侠,想实现double保留5位小数,不四舍五入,应该怎么实现)
2026年3月28日 23:00
c***t char 和char(c语言char和c***t char区别)
2026年3月28日 22:40
vb round函数怎么使用(vb 数据四舍五入取到小数点后两位)
2026年3月28日 22:20






