首页 > 技术文章 > BigDecimal类处理高精度计算

appc 2018-03-27 10:20 原文

Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作啦!

(一)BigDecimal类的常用的几个构造方法

  • BigDecimal(int):将int表示形式转换为BigDecimal对象
  • BigDecimal(String) :将字符串表示形式转换为BigDecimal对象
  • BigDecimal(double):将double表示形式转换为BigDecimal对象

(二)BigDecimal类的常用方法

  • add(BigDecimal):BigDecimal对象中的值相加,返回BigDecimal对象
  • subtract(BigDecimal):BigDecimal对象中的值相减,返回BigDecimal对象
  • multiply(BigDecimal):BigDecimal对象中的值相乘,返回BigDecimal对象
  • divide(BigDecimal):BigDecimal对象中的值相除,返回BigDecimal对象
  • toString():将BigDecimal对象中的值转换成字符串
  • doubleValue():将BigDecimal对象中的值转换成双精度数
  • floatValue():将BigDecimal对象中的值转换成单精度数
  • longValue():将BigDecimal对象中的值转换成长整数
  • intValue():将BigDecimal对象中的值转换成整数

下面分享一个用于高精确处理常用的数学运算类

  1 package com.per.test;
  2 
  3 import java.math.BigDecimal;
  4 
  5 /**
  6  * 用于高精确处理常用的数学运算
  7  * Created by lijuan on 2016/8/27.
  8  */
  9 public class ArithmeticUtils {
 10     //默认除法运算精度
 11     private static final int DEF_DIV_SCALE = 10;
 12 
 13     /**
 14      * 提供精确的加法运算
 15      *
 16      * @param v1 被加数
 17      * @param v2 加数
 18      * @return 两个参数的和
 19      */
 20 
 21     public static double add(double v1, double v2) {
 22         BigDecimal b1 = new BigDecimal(Double.toString(v1));
 23         BigDecimal b2 = new BigDecimal(Double.toString(v2));
 24         return b1.add(b2).doubleValue();
 25     }
 26 
 27     /**
 28      * 提供精确的加法运算
 29      *
 30      * @param v1 被加数
 31      * @param v2 加数
 32      * @return 两个参数的和
 33      */
 34     public static BigDecimal add(String v1, String v2) {
 35         BigDecimal b1 = new BigDecimal(v1);
 36         BigDecimal b2 = new BigDecimal(v2);
 37         return b1.add(b2);
 38     }
 39 
 40     /**
 41      * 提供精确的加法运算
 42      *
 43      * @param v1    被加数
 44      * @param v2    加数
 45      * @param scale 保留scale 位小数
 46      * @return 两个参数的和
 47      */
 48     public static String add(String v1, String v2, int scale) {
 49         if (scale < 0) {
 50             throw new IllegalArgumentException(
 51                     "The scale must be a positive integer or zero");
 52         }
 53         BigDecimal b1 = new BigDecimal(v1);
 54         BigDecimal b2 = new BigDecimal(v2);
 55         return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
 56     }
 57 
 58     /**
 59      * 提供精确的减法运算
 60      *
 61      * @param v1 被减数
 62      * @param v2 减数
 63      * @return 两个参数的差
 64      */
 65     public static double sub(double v1, double v2) {
 66         BigDecimal b1 = new BigDecimal(Double.toString(v1));
 67         BigDecimal b2 = new BigDecimal(Double.toString(v2));
 68         return b1.subtract(b2).doubleValue();
 69     }
 70 
 71     /**
 72      * 提供精确的减法运算。
 73      *
 74      * @param v1 被减数
 75      * @param v2 减数
 76      * @return 两个参数的差
 77      */
 78     public static BigDecimal sub(String v1, String v2) {
 79         BigDecimal b1 = new BigDecimal(v1);
 80         BigDecimal b2 = new BigDecimal(v2);
 81         return b1.subtract(b2);
 82     }
 83 
 84     /**
 85      * 提供精确的减法运算
 86      *
 87      * @param v1    被减数
 88      * @param v2    减数
 89      * @param scale 保留scale 位小数
 90      * @return 两个参数的差
 91      */
 92     public static String sub(String v1, String v2, int scale) {
 93         if (scale < 0) {
 94             throw new IllegalArgumentException(
 95                     "The scale must be a positive integer or zero");
 96         }
 97         BigDecimal b1 = new BigDecimal(v1);
 98         BigDecimal b2 = new BigDecimal(v2);
 99         return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
100     }
101 
102     /**
103      * 提供精确的乘法运算
104      *
105      * @param v1 被乘数
106      * @param v2 乘数
107      * @return 两个参数的积
108      */
109     public static double mul(double v1, double v2) {
110         BigDecimal b1 = new BigDecimal(Double.toString(v1));
111         BigDecimal b2 = new BigDecimal(Double.toString(v2));
112         return b1.multiply(b2).doubleValue();
113     }
114 
115     /**
116      * 提供精确的乘法运算
117      *
118      * @param v1 被乘数
119      * @param v2 乘数
120      * @return 两个参数的积
121      */
122     public static BigDecimal mul(String v1, String v2) {
123         BigDecimal b1 = new BigDecimal(v1);
124         BigDecimal b2 = new BigDecimal(v2);
125         return b1.multiply(b2);
126     }
127 
128 
129     /**
130      * 提供精确的乘法运算
131      *
132      * @param v1    被乘数
133      * @param v2    乘数
134      * @param scale 保留scale 位小数
135      * @return 两个参数的积
136      */
137     public static double mul(double v1, double v2, int scale) {
138         BigDecimal b1 = new BigDecimal(Double.toString(v1));
139         BigDecimal b2 = new BigDecimal(Double.toString(v2));
140         return round(b1.multiply(b2).doubleValue(), scale);
141     }
142 
143     /**
144      * 提供精确的乘法运算
145      *
146      * @param v1    被乘数
147      * @param v2    乘数
148      * @param scale 保留scale 位小数
149      * @return 两个参数的积
150      */
151     public static String mul(String v1, String v2, int scale) {
152         if (scale < 0) {
153             throw new IllegalArgumentException(
154                     "The scale must be a positive integer or zero");
155         }
156         BigDecimal b1 = new BigDecimal(v1);
157         BigDecimal b2 = new BigDecimal(v2);
158         return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
159     }
160 
161     /**
162      * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
163      * 小数点以后10位,以后的数字四舍五入
164      *
165      * @param v1 被除数
166      * @param v2 除数
167      * @return 两个参数的商
168      */
169 
170     public static double div(double v1, double v2) {
171         return div(v1, v2, DEF_DIV_SCALE);
172     }
173 
174     /**
175      * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
176      * 定精度,以后的数字四舍五入
177      *
178      * @param v1    被除数
179      * @param v2    除数
180      * @param scale 表示表示需要精确到小数点以后几位。
181      * @return 两个参数的商
182      */
183     public static double div(double v1, double v2, int scale) {
184         if (scale < 0) {
185             throw new IllegalArgumentException("The scale must be a positive integer or zero");
186         }
187         BigDecimal b1 = new BigDecimal(Double.toString(v1));
188         BigDecimal b2 = new BigDecimal(Double.toString(v2));
189         return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
190     }
191 
192     /**
193      * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
194      * 定精度,以后的数字四舍五入
195      *
196      * @param v1    被除数
197      * @param v2    除数
198      * @param scale 表示需要精确到小数点以后几位
199      * @return 两个参数的商
200      */
201     public static String div(String v1, String v2, int scale) {
202         if (scale < 0) {
203             throw new IllegalArgumentException("The scale must be a positive integer or zero");
204         }
205         BigDecimal b1 = new BigDecimal(v1);
206         BigDecimal b2 = new BigDecimal(v1);
207         return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
208     }
209 
210     /**
211      * 提供精确的小数位四舍五入处理
212      *
213      * @param v     需要四舍五入的数字
214      * @param scale 小数点后保留几位
215      * @return 四舍五入后的结果
216      */
217     public static double round(double v, int scale) {
218         if (scale < 0) {
219             throw new IllegalArgumentException("The scale must be a positive integer or zero");
220         }
221         BigDecimal b = new BigDecimal(Double.toString(v));
222         return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
223     }
224 
225     /**
226      * 提供精确的小数位四舍五入处理
227      *
228      * @param v     需要四舍五入的数字
229      * @param scale 小数点后保留几位
230      * @return 四舍五入后的结果
231      */
232     public static String round(String v, int scale) {
233         if (scale < 0) {
234             throw new IllegalArgumentException(
235                     "The scale must be a positive integer or zero");
236         }
237         BigDecimal b = new BigDecimal(v);
238         return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
239     }
240 
241 
242     /**
243      * 取余数
244      *
245      * @param v1    被除数
246      * @param v2    除数
247      * @param scale 小数点后保留几位
248      * @return 余数
249      */
250     public static String remainder(String v1, String v2, int scale) {
251         if (scale < 0) {
252             throw new IllegalArgumentException(
253                     "The scale must be a positive integer or zero");
254         }
255         BigDecimal b1 = new BigDecimal(v1);
256         BigDecimal b2 = new BigDecimal(v2);
257         return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
258     }
259 
260     /**
261      * 取余数  BigDecimal
262      *
263      * @param v1    被除数
264      * @param v2    除数
265      * @param scale 小数点后保留几位
266      * @return 余数
267      */
268     public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {
269         if (scale < 0) {
270             throw new IllegalArgumentException(
271                     "The scale must be a positive integer or zero");
272         }
273         return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);
274     }
275 
276     /**
277      * 比较大小
278      *
279      * @param v1 被比较数
280      * @param v2 比较数
281      * @return 如果v1 大于v2 则 返回true 否则false
282      */
283     public static boolean compare(String v1, String v2) {
284         BigDecimal b1 = new BigDecimal(v1);
285         BigDecimal b2 = new BigDecimal(v2);
286         int bj = b1.compareTo(b2);
287         boolean res;
288         if (bj > 0)
289             res = true;
290         else
291             res = false;
292         return res;
293     }
294 }

 

推荐阅读