java里面的高精度运算

Posted 代码吴彦祖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java里面的高精度运算相关的知识,希望对你有一定的参考价值。

 1 package com.lv.study.am.first;
 2 
 3 import java.math.BigDecimal;
 4 
 5 public class TestBigDecimal {
 6 
 7     public static void main(String[] args) {
 8 
 9         // double d1=1.0;
10         // double d2=0.9;
11 
12         // System.out.println(d1-d2);//0.1
13 
14         // 计算机语言-》 二进制 01
15 
16         // 计算10/3
17 
18         // 漏洞 吧小数点后小于2角的全部打到自己的账号里面
19 
20         // test1();
21         // test3();
22         test4();
23 
24     }
25 
26     // 减法
27     public static void test4() {
28         BigDecimal bd1 = new BigDecimal(1.0);// 这个类没有无参的构造器
29         BigDecimal bd2 = new BigDecimal(0.9999);
30 
31         BigDecimal result = bd1.subtract(bd2);//
32 
33         System.out.println(result.floatValue());// 得到浮点类型
34         System.out.println(result.intValue());//得到int类型
35         System.out.println(result.longValue());
36 
37         System.out.println(result.setScale(10,BigDecimal.ROUND_HALF_UP));
38         
39         System.out.printf("%");
40     }
41 
42     // 乘法
43     public static void test3() {
44         BigDecimal bd1 = new BigDecimal(1.0);// 这个类没有无参的构造器
45         BigDecimal bd2 = new BigDecimal(0.9);
46 
47         BigDecimal result = bd1.multiply(bd2);//
48 
49         System.out.println(result.floatValue());// 得到浮点类型
50         System.out.println(result.intValue());
51     }
52 
53     // 加法
54     public static void test2() {
55         BigDecimal bd1 = new BigDecimal(1.0);// 这个类没有无参的构造器
56         BigDecimal bd2 = new BigDecimal(0.9);
57 
58         BigDecimal result = bd1.add(bd2);// 做加法
59 
60         System.out.println(result.floatValue());// 得到浮点类型
61         System.out.println(result.intValue());
62     }
63 
64     public static void test1() {
65 
66         BigDecimal bd1 = new BigDecimal(1.0);// 这个类没有无参的构造器
67         BigDecimal bd2 = new BigDecimal(0.9);
68 
69         // 在计算时候没有指定余下多少位小数和他的小数怎么进位就会报异常
70         // System.out.println(bd1.divide(bd2).setScale(2,BigDecimal.ROUND_HALF_UP));//
71         // 1/0.9->1.1111111
72 
73         // bd1: 被除数 bd2: 除数 2:留下的几位小数 ROUND_HALF_UP :四舍五入
74         System.out.println(bd1.divide(bd2, 2, BigDecimal.ROUND_HALF_UP));// 静态常量所有字母大写
75 
76         // 一般涉及到比较敏感的金额不会用double
77         Double d1 = new Double(1.0);
78         Double d2 = new Double(0.9);
79 
80         // 除法运算
81         // System.out.println(d1/d2);
82         // System.out.println(d1+d2);
83         // System.out.println(d1-d2);
84         // System.out.println(d1*d2);
85     }
86 
87 }

下面具体讲解

  1 BigDecimal类处理高精度计算
  2 Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度。所以开发中,如果我们需要精确计算的结果,则必须使用BigDecimal类来操作啦!
  3 
  4 (一)BigDecimal类的常用的几个构造方法
  5 
  6 BigDecimal(int):将int表示形式转换为BigDecimal对象
  7 BigDecimal(String) :将字符串表示形式转换为BigDecimal对象
  8 BigDecimal(double):将double表示形式转换为BigDecimal对象
  9 (二)BigDecimal类的常用方法
 10 
 11 add(BigDecimal):BigDecimal对象中的值相加,返回BigDecimal对象
 12 subtract(BigDecimal):BigDecimal对象中的值相减,返回BigDecimal对象
 13 multiply(BigDecimal):BigDecimal对象中的值相乘,返回BigDecimal对象
 14 divide(BigDecimal):BigDecimal对象中的值相除,返回BigDecimal对象
 15 toString():将BigDecimal对象中的值转换成字符串
 16 doubleValue():将BigDecimal对象中的值转换成双精度数
 17 floatValue():将BigDecimal对象中的值转换成单精度数
 18 longValue():将BigDecimal对象中的值转换成长整数
 19 intValue():将BigDecimal对象中的值转换成整数
 20 
 21 //常用的;一般情况下,使用的都是四舍五入
 22 BigDecimal.ROUND_HALF_UP表示四舍五入,
 23 BigDecimal.ROUND_HALF_DOWN也是五舍六入,
 24 BigDecimal.ROUND_UP表示进位处理(就是直接加1),
 25 BigDecimal.ROUND_DOWN表示直接去掉尾数。
 26 1: 加减乘除
 27 BigDecimal bignum1 = new BigDecimal("10");  
 28 BigDecimal bignum2 = new BigDecimal("5");  
 29 BigDecimal bignum3 = null;  
 30   
 31 //加法  
 32 bignum3 =  bignum1.add(bignum2);       
 33 System.out.println("和 是:" + bignum3);  
 34   
 35 //减法  
 36 bignum3 = bignum1.subtract(bignum2);  
 37 System.out.println("差  是:" + bignum3);  
 38   
 39 //乘法  
 40 bignum3 = bignum1.multiply(bignum2);  
 41 System.out.println("积  是:" + bignum3);  
 42   
 43 //除法  
 44 bignum3 = bignum1.divide(bignum2);  
 45 System.out.println("商  是:" + bignum3); 
 46 
 47 2: 比较大小
 48 
 49 BigDecimal a = new BigDecimal (888);
 50 BigDecimal b = new BigDecimal (666);
 51  
 52 //使用compareTo方法比较
 53 //注意:a、b均不能为null,否则会报空指针
 54 if(a.compareTo(b) == -1){
 55     System.out.println("a小于b");
 56 }
 57  
 58 if(a.compareTo(b) == 0){
 59     System.out.println("a等于b");
 60 }
 61  
 62 if(a.compareTo(b) == 1){
 63     System.out.println("a大于b");
 64 }
 65  
 66 if(a.compareTo(b) > -1){
 67     System.out.println("a大于等于b");
 68 }
 69  
 70 if(a.compareTo(b) < 1){
 71     System.out.println("a小于等于b");
 72 
 73 // 四舍五入  保留两位小数
 74 new BigDecimal("1024.1234").setScale(2,BigDecimal.ROUND_HALF_UP);
 75 
 76 
 77 
 78 //默认除法运算精度
 79     private static final int DEF_DIV_SCALE = 10;
 80  
 81     /**
 82      * 提供精确的加法运算
 83      *
 84      * @param v1 被加数
 85      * @param v2 加数
 86      * @return 两个参数的和
 87      */
 88  
 89     public static double add(double v1, double v2) {
 90         BigDecimal b1 = new BigDecimal(Double.toString(v1));
 91         BigDecimal b2 = new BigDecimal(Double.toString(v2));
 92         return b1.add(b2).doubleValue();
 93     }
 94  
 95     /**
 96      * 提供精确的加法运算
 97      *
 98      * @param v1 被加数
 99      * @param v2 加数
100      * @return 两个参数的和
101      */
102     public static BigDecimal add(String v1, String v2) {
103         BigDecimal b1 = new BigDecimal(v1);
104         BigDecimal b2 = new BigDecimal(v2);
105         return b1.add(b2);
106     }
107  
108     /**
109      * 提供精确的加法运算
110      *
111      * @param v1    被加数
112      * @param v2    加数
113      * @param scale 保留scale 位小数
114      * @return 两个参数的和
115      */
116     public static String add(String v1, String v2, int scale) {
117         if (scale < 0) {
118             throw new IllegalArgumentException(
119                     "The scale must be a positive integer or zero");
120         }
121         BigDecimal b1 = new BigDecimal(v1);
122         BigDecimal b2 = new BigDecimal(v2);
123         return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
124     }
125  
126     /**
127      * 提供精确的减法运算
128      *
129      * @param v1 被减数
130      * @param v2 减数
131      * @return 两个参数的差
132      */
133     public static double sub(double v1, double v2) {
134         BigDecimal b1 = new BigDecimal(Double.toString(v1));
135         BigDecimal b2 = new BigDecimal(Double.toString(v2));
136         return b1.subtract(b2).doubleValue();
137     }
138  
139     /**
140      * 提供精确的减法运算。
141      *
142      * @param v1 被减数
143      * @param v2 减数
144      * @return 两个参数的差
145      */
146     public static BigDecimal sub(String v1, String v2) {
147         BigDecimal b1 = new BigDecimal(v1);
148         BigDecimal b2 = new BigDecimal(v2);
149         return b1.subtract(b2);
150     }
151  
152     /**
153      * 提供精确的减法运算
154      *
155      * @param v1    被减数
156      * @param v2    减数
157      * @param scale 保留scale 位小数
158      * @return 两个参数的差
159      */
160     public static String sub(String v1, String v2, int scale) {
161         if (scale < 0) {
162             throw new IllegalArgumentException(
163                     "The scale must be a positive integer or zero");
164         }
165         BigDecimal b1 = new BigDecimal(v1);
166         BigDecimal b2 = new BigDecimal(v2);
167         return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
168     }
169  
170     /**
171      * 提供精确的乘法运算
172      *
173      * @param v1 被乘数
174      * @param v2 乘数
175      * @return 两个参数的积
176      */
177     public static double mul(double v1, double v2) {
178         BigDecimal b1 = new BigDecimal(Double.toString(v1));
179         BigDecimal b2 = new BigDecimal(Double.toString(v2));
180         return b1.multiply(b2).doubleValue();
181     }
182  
183     /**
184      * 提供精确的乘法运算
185      *
186      * @param v1 被乘数
187      * @param v2 乘数
188      * @return 两个参数的积
189      */
190     public static BigDecimal mul(String v1, String v2) {
191         BigDecimal b1 = new BigDecimal(v1);
192         BigDecimal b2 = new BigDecimal(v2);
193         return b1.multiply(b2);
194     }
195  
196  
197     /**
198      * 提供精确的乘法运算
199      *
200      * @param v1    被乘数
201      * @param v2    乘数
202      * @param scale 保留scale 位小数
203      * @return 两个参数的积
204      */
205     public static double mul(double v1, double v2, int scale) {
206         BigDecimal b1 = new BigDecimal(Double.toString(v1));
207         BigDecimal b2 = new BigDecimal(Double.toString(v2));
208         return round(b1.multiply(b2).doubleValue(), scale);
209     }
210  
211     /**
212      * 提供精确的乘法运算
213      *
214      * @param v1    被乘数
215      * @param v2    乘数
216      * @param scale 保留scale 位小数
217      * @return 两个参数的积
218      */
219     public static String mul(String v1, String v2, int scale) {
220         if (scale < 0) {
221             throw new IllegalArgumentException(
222                     "The scale must be a positive integer or zero");
223         }
224         BigDecimal b1 = new BigDecimal(v1);
225         BigDecimal b2 = new BigDecimal(v2);
226         return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
227     }
228  
229     /**
230      * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
231      * 小数点以后10位,以后的数字四舍五入
232      *
233      * @param v1 被除数
234      * @param v2 除数
235      * @return 两个参数的商
236      */
237  
238     public static double div(double v1, double v2) {
239         return div(v1, v2, DEF_DIV_SCALE);
240     }
241  
242     /**
243      * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
244      * 定精度,以后的数字四舍五入
245      *
246      * @param v1    被除数
247      * @param v2    除数
248      * @param scale 表示表示需要精确到小数点以后几位。
249      * @return 两个参数的商
250      */
251     public static double div(double v1, double v2, int scale) {
252         if (scale < 0) {
253             throw new IllegalArgumentException("The scale must be a positive integer or zero");
254         }
255         BigDecimal b1 = new BigDecimal(Double.toString(v1));
256         BigDecimal b2 = new BigDecimal(Double.toString(v2));
257         return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
258     }
259  
260     /**
261      * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
262      * 定精度,以后的数字四舍五入
263      *
264      * @param v1    被除数
265      * @param v2    除数
266      * @param scale 表示需要精确到小数点以后几位
267      * @return 两个参数的商
268      */
269     public static String div(String v1, String v2, int scale) {
270         if (scale < 0) {
271             throw new IllegalArgumentException("The scale must be a positive integer or zero");
272         }
273         BigDecimal b1 = new BigDecimal(v1);
274         BigDecimal b2 = new BigDecimal(v1);
275         return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
276     }
277  
278     /**
279      * 提供精确的小数位四舍五入处理
280      *
281      * @param v     需要四舍五入的数字
282      * @param scale 小数点后保留几位
283      * @return 四舍五入后的结果
284      */
285     public static double round(double v, int scale) {
286         if (scale < 0) {
287             throw new IllegalArgumentException("The scale must be a positive integer or zero");
288         }
289         BigDecimal b = new BigDecimal(Double.toString(v));
290         return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
291     }
292  
293     /**
294      * 提供精确的小数位四舍五入处理
295      *
296      * @param v     需要四舍五入的数字
297      * @param scale 小数点后保留几位
298      * @return 四舍五入后的结果
299      */
300     public static String round(String v, int scale) {
301         if (scale < 0) {
302             throw new IllegalArgumentException(
303                     "The scale must be a positive integer or zero");
304         }
305         BigDecimal b = new BigDecimal(v);
306         return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
307     }
308  
309  
310     /**
311      * 取余数
312      *
313      * @param v1    被除数
314      * @param v2    除数
315      * @param scale 小数点后保留几位
316      * @return 余数
317      */
318     public static String remainder(String v1, String v2, int scale) {
319         if (scale < 0) {
320             throw new IllegalArgumentException(
321                     "The scale must be a positive integer or zero");
322         }
323         BigDecimal b1 = new BigDecimal(v1);
324         BigDecimal b2 = new BigDecimal(v2);
325         return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
326     }
327  
328     /**
329      * 取余数  BigDecimal
330      *
331      * @param v1    被除数
332      * @param v2    除数
333      * @param scale 小数点后保留几位
334      * @return 余数
335      */
336     public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {
337         if (scale < 0) {
338             throw new IllegalArgumentException(
339                     "The scale must be a positive integer or zero");
340         }
341         return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);
342     }
343  
344     /**
345      * 比较大小
346      *
347      * @param v1 被比较数
348      * @param v2 比较数
349      * @return 如果v1 大于v2 则 返回true 否则false
350      */
351     public static boolean compare(String v1, String v2) {
352         BigDecimal b1 = new BigDecimal(v1);
353         BigDecimal b2 = new BigDecimal(v2);
354         int bj = b1.compareTo(b2);
355         boolean res;
356         if (bj > 0)
357             res = true;
358         else
359             res = false;
360         return res;
361     }

 

以上是关于java里面的高精度运算的主要内容,如果未能解决你的问题,请参考以下文章

第49题常用的数学工具类6-高精度整数运算

第50题常用的数学工具类7-高精度浮点运算

高精度运算 Java算法

04-JAVA高精度数字

JAVA高精度计算工具

Java 避免精度丢失之BigDecimal 运算