一、BigDeci***l概述
java.***th包中提供的API类BigDeci***l用于对超过16个有效位的数字执行精确运算。双精度浮点变量Double可以处理16位有效数,但在实际应用中,可能需要运算和处理更大或更小的数。对于那些不需要精确计算精度的数字,一般我们可以直接使用Float和Double处理,但是Double.valueOf(String)和Float.valueOf(String)会损失精度。所以在开发中,如果需要精确计算的结果,就必须使用BigDeci***l类来操作。
BigDeci***l创建的是一个对象,所以不能用+、-、*、/等传统的算术运算符直接对其对象进行数**算,而必须调用其对应的方法。方法中的参数也必须是BigDeci***l的对象。构造函数是类的一种特殊方法,专门用来创建对象,尤其是带参数的对象。
二、BigDeci***l常见构造函数
2.1.通用构造函数
BigDeci***l(int) 创建一个具有参数所指定整数值的对象BigDeci***l(double) 创建一个具有参数所指定双精度值的对象BigDeci***l(long) 创建一个具有参数所指定长整数值的对象BigDeci***l(String) 创建一个具有参数所指定以字符串表示的数值的对象
2.2.使用中的问题分析
使用示例:
BigDeci***l a =new BigDeci***l(0.1); System.out.println("a values is:"+a); System.out.println("====================="); BigDeci***l b =new BigDeci***l("0.1"); System.out.println("b values is:"+b);
结果示例:
a values is:0.1000000000000000055511151231257827021181583404541015625=====================b values is:0.1
原因分析:
1)具有双参数类型的构造方法的结果是不可预测的。有人可能会认为用Java写newBigDeci***l(0.1)创建的BigDeci***l正好等于0.1(非定标值1,其小数位数为1),但实际上等于0.1000000000000005这是因为0.1不能精确表示为double(或者在这种情况下,不能表示为任意有限长度的二进制小数)。这样,传入构造函数的值不会正好等于0.1(虽然表面上等于这个值)。
2)2)字符串构造方法是完全可以预测的:编写新的BigDeci***l ("0.1 ")将创建一个BigDeci***l,它正好等于预期的0.1。所以相比较而言,通常建议先用字符串构造法。
3)当double必须作为BigDeci***l的源时,请注意这种构造方法提供了准确的转换;它不会提供与以下操作相同的结果:首先使用Double.toString(Double)方法,然后使用BigDeci***l(String)构造方法将double转换为字符串。要获得结果,请使用静态valueOf(double)方法。
三。BigDeci***l常用方法详解
3.1.常用方法
add(BigDeci***l) BigDeci***l对象中的值相加,返回BigDeci***l对象subtract(BigDeci***l) BigDeci***l对象中的值相减,返回BigDeci***l对象multiply(BigDeci***l) BigDeci***l对象中的值相乘,返回BigDeci***l对象divide(BigDeci***l) BigDeci***l对象中的值相除,返回BigDeci***l对象toString() 将BigDeci***l对象中的值转换成字符串doubleValue() 将BigDeci***l对象中的值转换成双精度数floatValue() 将BigDeci***l对象中的值转换成单精度数longValue() 将BigDeci***l对象中的值转换成长整数intValue() 将BigDeci***l对象中的值转换成整数
3.2.BigDeci***l大小比较
在java中,BigDeci***l的compareTo方法一般用于比较BigDeci***l的大小。
int a = bigdemical.compareTo(bigdemical2)
返回结果分析:
a = -1,表示bigdemical小于bigdemical2;a = 0,表示bigdemical等于bigdemical2;a = 1,表示bigdemical大于bigdemical2;
例如:A大于等于b。
new bigdemica(a).compareTo(new bigdemical(b)) >= 0
四。BigDeci***l格式
因为NumberFor***t类的for***t()方法可以使用BigDeci***l对象作为其参数,所以可以使用BigDeci***l来格式化货币值、百分比值和超过16位有效数字的通用数值。
以BigDeci***l对货币和百分比的格式为例。首先创建一个BigDeci***l对象,在执行BigDeci***l的算术运算后,分别建立对货币和百分比格式的引用。最后使用BigDeci***l对象作为for***t()方法的参数,输出其格式化后的货币值和百分比。
NumberFor***t currency = NumberFor***t.getCurrencyInstance(); //建立货币格式化引用 NumberFor***t percent = NumberFor***t.getPercentInstance(); //建立百分比格式化引用 percent.setMaximumFractionDigits(3); //百分比小数点最多3位 BigDeci***l loanAmount = new BigDeci***l("15000.48"); //贷款金额 BigDeci***l interestRate = new BigDeci***l("0.008"); //利率 BigDeci***l interest = loanAmount.multiply(interestRate); //相乘 System.out.println("贷款金额:t" + currency.for***t(loanAmount)); System.out.println("利率:t" + percent.for***t(interestRate)); System.out.println("利息:t" + currency.for***t(interest));
结果:
贷款金额: ¥15,000.48 利率: 0.8% 利息: ¥120.00
BigDeci***l格式将2保留为十进制数,如果不足,则添加0:
public class NumberFor***t {public static void ***in(String[] s){System.out.println(for***tToNumber(new BigDeci***l("3.435")));System.out.println(for***tToNumber(new BigDeci***l(0)));System.out.println(for***tToNumber(new BigDeci***l("0.00")));System.out.println(for***tToNumber(new BigDeci***l("0.001")));System.out.println(for***tToNumber(new BigDeci***l("0.006")));System.out.println(for***tToNumber(new BigDeci***l("0.206"))); }/** * @desc 1.0~1之间的BigDeci***l小数,格式化后失去前面的0,则前面直接加上0。 * 2.传入的参数等于0,则直接返回字符串"0.00" * 3.大于1的小数,直接格式化返回字符串 * @param obj传入的小数 * @return */public static String for***tToNumber(BigDeci***l obj) {Deci***lFor***t df = new Deci***lFor***t("#.00");if(obj.compareTo(BigDeci***l.ZERO)==0) {return "0.00";}else if(obj.compareTo(BigDeci***l.ZERO)>0&&obj.compareTo(new BigDeci***l(1))<0){return "0"+df.for***t(obj).toString();}else {return df.for***t(obj).toString();}}}
结果是:
3.440.000.000.000.010.21
动词 (verb的缩写)BigDeci***l的常见异常
5.1.除法有例外。
java.lang.ArithmeticException: Non-terminating deci***l expansion; no exact representable deci***l result
原因分析:
用BigDeci***l的divide方法进行除法运算时,当出现无限循环小数时,会抛出异常:java.lang.arithmeticException:非终止小数展开;没有精确可表示的十进制结果。
解决方法:
divide方法设置精确的小数点,例如divide(xxxxx,2)
不及物动词BigDeci***l汇总
6.1.摘要
在需要精确的小数计算时再使用BigDeci***l,BigDeci***l的性能比double和float差,在处理庞大,复杂的运算时尤为明显。故一般精度的计算没必要使用BigDeci***l。尽量使用参数类型为String的构造函数。BigDeci***l都是不可变的(immutable)的, 在进行每一次四则运算时,都会产生一个新的对象 ,所以在做加减乘除运算时要记得要保存操作后的值。
6.2.推荐工具
package com.vivo.ars.util;import java.***th.BigDeci***l;/** * 用于高精确处理常用的数**算 */public class ArithmeticUtils { //默认除法运算精度 private static final int DEF_DIV_SCALE = 10; /** * 提供精确的加法运算 * * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ public static double add(double v1, double v2) { BigDeci***l b1 = new BigDeci***l(Double.toString(v1)); BigDeci***l b2 = new BigDeci***l(Double.toString(v2)); return b1.add(b2).doubleValue(); } /** * 提供精确的加法运算 * * @param v1 被加数 * @param v2 加数 * @return 两个参数的和 */ public static BigDeci***l add(String v1, String v2) { BigDeci***l b1 = new BigDeci***l(v1); BigDeci***l b2 = new BigDeci***l(v2); return b1.add(b2); } /** * 提供精确的加法运算 * * @param v1 被加数 * @param v2 加数 * @param scale 保留scale 位小数 * @return 两个参数的和 */ public static String add(String v1, String v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDeci***l b1 = new BigDeci***l(v1); BigDeci***l b2 = new BigDeci***l(v2); return b1.add(b2).setScale(scale, BigDeci***l.ROUND_HALF_UP).toString(); } /** * 提供精确的减法运算 * * @param v1 被减数 * @param v2 减数 * @return 两个参数的差 */ public static double sub(double v1, double v2) { BigDeci***l b1 = new BigDeci***l(Double.toString(v1)); BigDeci***l b2 = new BigDeci***l(Double.toString(v2)); return b1.subtract(b2).doubleValue(); } /** * 提供精确的减法运算。 * * @param v1 被减数 * @param v2 减数 * @return 两个参数的差 */ public static BigDeci***l sub(String v1, String v2) { BigDeci***l b1 = new BigDeci***l(v1); BigDeci***l b2 = new BigDeci***l(v2); return b1.subtract(b2); } /** * 提供精确的减法运算 * * @param v1 被减数 * @param v2 减数 * @param scale 保留scale 位小数 * @return 两个参数的差 */ public static String sub(String v1, String v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDeci***l b1 = new BigDeci***l(v1); BigDeci***l b2 = new BigDeci***l(v2); return b1.subtract(b2).setScale(scale, BigDeci***l.ROUND_HALF_UP).toString(); } /** * 提供精确的乘法运算 * * @param v1 被乘数 * @param v2 乘数 * @return 两个参数的积 */ public static double mul(double v1, double v2) { BigDeci***l b1 = new BigDeci***l(Double.toString(v1)); BigDeci***l b2 = new BigDeci***l(Double.toString(v2)); return b1.multiply(b2).doubleValue(); } /** * 提供精确的乘法运算 * * @param v1 被乘数 * @param v2 乘数 * @return 两个参数的积 */ public static BigDeci***l mul(String v1, String v2) { BigDeci***l b1 = new BigDeci***l(v1); BigDeci***l b2 = new BigDeci***l(v2); return b1.multiply(b2); } /** * 提供精确的乘法运算 * * @param v1 被乘数 * @param v2 乘数 * @param scale 保留scale 位小数 * @return 两个参数的积 */ public static double mul(double v1, double v2, int scale) { BigDeci***l b1 = new BigDeci***l(Double.toString(v1)); BigDeci***l b2 = new BigDeci***l(Double.toString(v2)); return round(b1.multiply(b2).doubleValue(), scale); } /** * 提供精确的乘法运算 * * @param v1 被乘数 * @param v2 乘数 * @param scale 保留scale 位小数 * @return 两个参数的积 */ public static String mul(String v1, String v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDeci***l b1 = new BigDeci***l(v1); BigDeci***l b2 = new BigDeci***l(v2); return b1.multiply(b2).setScale(scale, BigDeci***l.ROUND_HALF_UP).toString(); } /** * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 * 小数点以后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"); } BigDeci***l b1 = new BigDeci***l(Double.toString(v1)); BigDeci***l b2 = new BigDeci***l(Double.toString(v2)); return b1.divide(b2, scale, BigDeci***l.ROUND_HALF_UP).doubleValue(); } /** * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 * 定精度,以后的数字四舍五入 * * @param v1 被除数 * @param v2 除数 * @param scale 表示需要精确到小数点以后几位 * @return 两个参数的商 */ public static String div(String v1, String v2, int scale) { if (scale < 0) { throw new IllegalArgumentException("The scale must be a positive integer or zero"); } BigDeci***l b1 = new BigDeci***l(v1); BigDeci***l b2 = new BigDeci***l(v1); return b1.divide(b2, scale, BigDeci***l.ROUND_HALF_UP).toString(); } /** * 提供精确的小数位四舍五入处理 * * @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"); } BigDeci***l b = new BigDeci***l(Double.toString(v)); return b.setScale(scale, BigDeci***l.ROUND_HALF_UP).doubleValue(); } /** * 提供精确的小数位四舍五入处理 * * @param v 需要四舍五入的数字 * @param scale 小数点后保留几位 * @return 四舍五入后的结果 */ public static String round(String v, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDeci***l b = new BigDeci***l(v); return b.setScale(scale, BigDeci***l.ROUND_HALF_UP).toString(); } /** * 取余数 * * @param v1 被除数 * @param v2 除数 * @param scale 小数点后保留几位 * @return 余数 */ public static String re***inder(String v1, String v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDeci***l b1 = new BigDeci***l(v1); BigDeci***l b2 = new BigDeci***l(v2); return b1.re***inder(b2).setScale(scale, BigDeci***l.ROUND_HALF_UP).toString(); } /** * 取余数 BigDeci***l * * @param v1 被除数 * @param v2 除数 * @param scale 小数点后保留几位 * @return 余数 */ public static BigDeci***l re***inder(BigDeci***l v1, BigDeci***l v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } return v1.re***inder(v2).setScale(scale, BigDeci***l.ROUND_HALF_UP); } /** * 比较大小 * * @param v1 被比较数 * @param v2 比较数 * @return 如果v1 大于v2 则 返回true 否则false */ public static boolean compare(String v1, String v2) { BigDeci***l b1 = new BigDeci***l(v1); BigDeci***l b2 = new BigDeci***l(v2); int bj = b1.compareTo(b2); boolean res; if (bj > 0) res = true; else res = false; return res; }}
本文来自又何必自找失落╮投稿,不代表舒华文档立场,如若转载,请注明出处:https://www.chinashuhua.cn/24/629650.html