一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - Java 高精度的大數(shù)字運(yùn)算方式

Java 高精度的大數(shù)字運(yùn)算方式

2021-11-17 13:36郎涯技術(shù) Java教程

這篇文章主要介紹了Java 高精度的大數(shù)字運(yùn)算方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Java 高精度的大數(shù)字運(yùn)算

為了解決Java基本數(shù)據(jù)類型在運(yùn)算時會出現(xiàn)的溢出和計算不精確的問題。Java 提供了兩個類BigInteger和BigDecimal,專門用于進(jìn)行高精度運(yùn)算。凡是能用int 或float 做的事情,用BigInteger和BigDecimal也可以做,只是必須換用方法調(diào)用,而不是使用運(yùn)算符。

高精度整數(shù)BigInteger

BigInteger支持任意精度的整數(shù),也就是說我們可精確表示任意大小的整數(shù)值;同時在運(yùn)算過程中不會丟失任何信息;

高精度浮點(diǎn)數(shù)BigDecimal

它可以表示任意精度的小數(shù),并對它們進(jìn)行計算。由于 BigDecimal 對象是不可變的,這些方法中的每一個都會產(chǎn)生新的 BigDecimal 對象。因此,因為創(chuàng)建對象的開銷,BigDecimal 不適合于大量的數(shù)學(xué)計算,但設(shè)計它的目的是用來精確地表示小數(shù)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import java.math.BigDecimal;
import java.math.BigInteger;
public class BigNumber {
//默認(rèn)除法運(yùn)算精度,即保留小數(shù)點(diǎn)多少位
private static final int DEFAULT_DIV_SCALE = 10;
//這個類不能實(shí)例化
private BigNumber() {
}
/**
* 提供精確的加法運(yùn)算。
* @param v1 被加數(shù)
* @param v2 加數(shù)
* @return 兩個參數(shù)的和
*/
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();
}
/**
* 提供精確的減法運(yùn)算。
* @param v1 被減數(shù)
* @param v2 減數(shù)
* @return 兩個參數(shù)的差
*/
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();
}
/**
* 提供精確的乘法運(yùn)算。
* @param v1 被乘數(shù)
* @param v2 乘數(shù)
* @return 兩個參數(shù)的積
*/
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();
}
/**
* 提供(相對)精確的除法運(yùn)算,當(dāng)發(fā)生除不盡的情況時,精確到
* 小數(shù)點(diǎn)以后多少位,以后的數(shù)字四舍五入。
* @param v1 被除數(shù)
* @param v2 除數(shù)
* @return 兩個參數(shù)的商
*/
public static double div(double v1, double v2) {
   return div(v1, v2, DEFAULT_DIV_SCALE);
}
/**
* 提供(相對)精確的除法運(yùn)算。當(dāng)發(fā)生除不盡的情況時,由scale參數(shù)指
* 定精度,以后的數(shù)字四舍五入。
* @param v1 被除數(shù)
* @param v2 除數(shù)
* @param scale 表示需要精確到小數(shù)點(diǎn)以后幾位。
* @return 兩個參數(shù)的商
*/
public static double div(double v1, double v2, int scale) {
   if (scale < 0) {
    System.err.println("除法精度必須大于0!");
    return 0;
   }
   BigDecimal b1 = new BigDecimal(Double.toString(v1));
   BigDecimal b2 = new BigDecimal(Double.toString(v2));
   return (b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP)).doubleValue();
}
/**
* 計算Factorial階乘!
* @param n   任意大于等于0的int
* @return     n!的值
*/
public static BigInteger getFactorial(int n) {
   if (n < 0) {
    System.err.println("n必須大于等于0!");
    return new BigInteger("-1");
   } else if (n == 0) {
    return new BigInteger("0");
   }
   //將數(shù)組換成字符串后構(gòu)造BigInteger
   BigInteger result = new BigInteger("1");
   for (; n > 0; n--) {
    //將數(shù)字n轉(zhuǎn)換成字符串后,再構(gòu)造一個BigInteger對象,與現(xiàn)有結(jié)果做乘法
    result = result.multiply(new BigInteger(new Integer(n).toString()));
   }
   return result;
}
public static void main(String[] args) {
   //   如果我們編譯運(yùn)行下面這個程序會看到什么?
   System.out.println(0.05 + 0.01);
   System.out.println(1.0 - 0.42);
   System.out.println(4.015 * 100);
   System.out.println(123.3 / 100);
   //   0.060000000000000005
   //   0.5800000000000001
   //   401.49999999999994
   //   1.2329999999999999
   //計算階乘,可以將n設(shè)得更大
   int n = 30;
   System.out.println("計算n的階乘" + n + "! = " + BigNumber.getFactorial(n));
   //用double構(gòu)造BigDecimal
   BigDecimal bd1 = new BigDecimal(0.1);
   System.out.println("(bd1 = new BigDecimal(0.1)) = " + bd1.toString());
   //用String構(gòu)造BigDecimal
   BigDecimal bd2 = new BigDecimal("0.1");
   System.out.println("(bd2 = new BigDecimal(\"0.1\")) = "
     + bd2.toString());
   BigDecimal bd3 = new BigDecimal("0.10");
   //equals方法比較兩個BigDecimal對象是否相等,相等返回true,不等返回false
   System.out.println("bd2.equals(bd3) = " + bd2.equals(bd3));//false
   //compareTo方法比較兩個BigDecimal對象的大小,相等返回0,小于返回-1,大于返回1。
   System.out.println("bd2.compareTo(bd3) = " + bd2.compareTo(bd3));//0
   //進(jìn)行精確計算
   System.out.println("0.05 + 0.01 = " + BigNumber.add(0.05, 0.01));
   System.out.println("1.0 - 0.42 = " + BigNumber.sub(1.0, 0.42));
   System.out.println("4.015 * 100 =" + BigNumber.mul(4.015, 100));
   System.out.println("123.3 / 100 = " + BigNumber.div(123.3, 100));
   }
}

(1)BigInteger和BigDecimal都是不可變(immutable)

在進(jìn)行每一步運(yùn)算時,都會產(chǎn)生一個新的對象,由于創(chuàng)建對象會引起開銷,它們不適合于大量的數(shù)學(xué)計算,應(yīng)盡量用long,float,double等基本類型做科學(xué)計算或者工程計算。
設(shè)計BigInteger和BigDecimal的目的是用來精確地表示大整數(shù)和小數(shù),使用于在商業(yè)計算中使用。

(2)BigDecimal有4個夠造方法

其中的兩個用BigInteger構(gòu)造,另一個是用double構(gòu)造,還有一個使用String構(gòu)造。
應(yīng)該避免使用double構(gòu)造BigDecimal,因為:有些數(shù)字用double根本無法精確表示,傳給BigDecimal構(gòu)造方法時就已經(jīng)不精確了。比如,new BigDecimal(0.1)得到的值是0.1000000000000000055511151231257827021181583404541015625。
使用new BigDecimal("0.1")得到的值是0.1。因此,如果需要精確計算,用String構(gòu)造BigDecimal,避免用double構(gòu)造,盡管它看起來更簡單!

(3)equals()方法認(rèn)為0.1和0.1是相等的

返回true,而認(rèn)為0.10和0.1是不等的,結(jié)果返回false。方法compareTo()則認(rèn)為0.1與0.1相等,0.10與0.1也相等。所以在從數(shù)值上比較兩個BigDecimal值時,應(yīng)該使用compareTo()而不是 equals()。

(4)另外還有一些情形

任意精度的小數(shù)運(yùn)算仍不能表示精確結(jié)果。例如,1除以9會產(chǎn)生無限循環(huán)的小數(shù) .111111...。
出于這個原因,在進(jìn)行除法運(yùn)算時,BigDecimal可以讓您顯式地控制舍入。

運(yùn)算結(jié)果:

0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999
計算n的階乘30! = 265252859812191058636308480000000
(bd1 = new BigDecimal(0.1)) = 0.1000000000000000055511151231257827021181583404541015625
(bd2 = new BigDecimal("0.1")) = 0.1
bd2.equals(bd3) = false
bd2.compareTo(bd3) = 0
0.05 + 0.01 = 0.06
1.0 - 0.42 = 1.42
4.015 * 100 =104.015
123.3 / 100 = 223.3

java超長數(shù)據(jù)高精度計算(僅支持整數(shù))

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/**
 * Created by AndyJuseKing on 2020/1/2.
 * 超長數(shù)據(jù)高精度計算
 * 僅支持整數(shù)
 */
public class CYAccuracy {
    private static String cyNum;
    private static String nowNum;
    public CYAccuracy(String a){
        cyNum = a;
    }
    public static void add(String n){
        cyNum = makeAdd(cyNum,n);
    }
    public static String getAdd(String n){
        nowNum = n;
        return makeAdd(cyNum,nowNum);
    }
    public static void subtract(String n){
        nowNum = n;
        cyNum = makeSubtract(cyNum,nowNum);
    }
    public static String getSubtract(String n){
        nowNum = n;
        return makeSubtract(cyNum,nowNum);
    }
    public static void multiply(String n){
        nowNum = n;
        cyNum = makeMultiply(cyNum,nowNum);
    }
    public static String getMultiply(String n){
        nowNum = n;
        return makeMultiply(cyNum,nowNum);
    }
    public static String[] divideAndRemainder(String n){
        nowNum = n;
        String h = cyNum;
        h = removeZero(h);
        String i = h;
        String divNum = "";
        String remNum = "";
        String a = "0";
        int c = h.length();
        int d = nowNum.length();
        int e = c;
        while (d<=e){
            String f = h;
            if(e==c){ f = h.substring(0, d); }
            String g = f;
            if(d<=c) {
                while (!f.contains("-")) {
                    g = f;
                    f = makeSubtract(f, n);
                    a = makeAdd(a, "1");
                    f = removeZero(f);
                }
                a = makeSubtract(a, "1");
                if(i.length()>=(d+divNum.length()+1)) {
                    h = addZero(g, 1);
                    h = makeAdd(h, i.substring(d + divNum.length(), d + 1 + divNum.length()));
                } else {
                    remNum = g;
                    e = 0;
                }
                c = h.length();
                divNum = divNum + a;
                a = "0";
            } else if(i.length()<(d+divNum.length()+1)){
                remNum = g;
                e = 0;
            } else {
                h = addZero(g, 1);
                h = makeAdd(h, i.substring(d+divNum.length(), d+1+divNum.length()));
                c = h.length();
                divNum = divNum + "0";
            }
        }
//        while (!newNum.contains("-")) {
//            newNum = makeSubtract(newNum,n);
//            a = makeAdd(a,"1");
//            newNum = removeZero(newNum);
//            System.out.print(newNum + "\n");
//        }
//        a = makeSubtract(a,"1");
//        b = newNum.substring(1);
        return (divNum+","+remNum).split(",");
    }
    public static Double getDouble(){
        return Double.parseDouble(cyNum);
    }
    public static Integer getInt(){
        return Integer.parseInt(cyNum);
    }
    public static String getString(){
        return cyNum;
    }
    private static String makeAdd(String x,String y){
        String newNum = "";
        int i = 1;if(x.substring(0,1).equals("-")){i = -1;}
        int j = 1;if(y.substring(0,1).equals("-")){j = -1;}
        int m = x.length();
        int n = y.length();
        if (m < n) {
            int c = n - m;
            for (int d = 0; d < c; d++) {
                x = "0" + x;
            }
        } else if (m > n) {
            int c = m - n;
            for (int d = 0; d < c; d++) {
                y = "0" + y;
            }
        }
        String[] a = x.split("");
        String[] b = y.split("");
        int g = 0;
        for(int c = a.length;c>0;c--){
            int d = c-1;
            int f = (Integer.parseInt(a[d])*i) + (Integer.parseInt(b[d])*j) + g;
            int e = f%10;
            newNum = e + newNum;
            g = f/10;
            if(d==0&&g!=0){
                newNum = g + newNum;
            }
        }
        return newNum;
    }
    private static String makeSubtract(String x,String y){
        String newNum = "";
        int m = x.length();
        int n = y.length();
        if (m < n) {
            int c = n - m;
            for (int d = 0; d < c; d++) {
                x = "0" + x;
            }
        } else if (m > n) {
            int c = m - n;
            for (int d = 0; d < c; d++) {
                y = "0" + y;
            }
        }
        String[] a = x.split("");
        String[] b = y.split("");
        int g = 0;
        for(int c = a.length;c>0;c--){
            int d = c-1;
            int h = Integer.parseInt(a[d]);
            int i = Integer.parseInt(b[d]);
            int f = (h - i) + g;
            int e = f%10;
            if(e==-1){ e = 9; }
            g = f/10;
            if(e<0){
                g = g-1;
                e = e * -1;
            }
            newNum = e + newNum;
            if(d==0&&g<0){
                newNum = "-" + newNum;
            }
        }
        return newNum;
    }
    private static String makeMultiply(String x,String y){
        String newNum = "0";
        String[] a = x.split("");
        String[] b = y.split("");
        String k = "";
        for(int h = b.length;h>0;h--) {
            int i = h - 1;
            k = k + "0";
            int g = 0;
            String j = "";
            for (int c = a.length; c > 0; c--) {
                int d = c - 1;
                int f = (Integer.parseInt(a[d])+g) * Integer.parseInt(b[i]);
                int e = f % 10;
                j = e + j;
                g = f / 10;
                if (d == 0 && g != 0) {
                    j = g + j;
                }
            }
            String l = j+k;
            newNum = makeAdd(newNum,l);
        }
        return newNum;
    }
    private static String removeZero(String x){
        String y = x;
        String[] a = x.split("");
        for(int b = 0;b<a.length;b++){
            if(y.substring(0,1).equals("0")){
                y = y.substring(1);
            }
        }
        if("".equals(y)){
            y = "0";
        }
        return y;
    }
    private static String addZero(String x,int length){
        while(length>0){
            x = x + "0";
            length--;
        }
        return x;
    }
}

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://langyastudio.blog.csdn.net/article/details/45840149

延伸 · 閱讀

精彩推薦
  • Java教程xml與Java對象的轉(zhuǎn)換詳解

    xml與Java對象的轉(zhuǎn)換詳解

    這篇文章主要介紹了xml與Java對象的轉(zhuǎn)換詳解的相關(guān)資料,需要的朋友可以參考下...

    Java教程網(wǎng)2942020-09-17
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關(guān)于小米推送Java代碼,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩(wěn)中求8032021-07-12
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經(jīng)有好久沒有升過級了。升級完畢重啟之后,突然發(fā)現(xiàn)好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程20個非常實(shí)用的Java程序代碼片段

    20個非常實(shí)用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實(shí)用的Java程序片段,對java開發(fā)項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發(fā)現(xiàn)了對于集合操作轉(zhuǎn)換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點(diǎn),所以這篇文章主要給大家介紹了關(guān)于Java8中S...

    阿杜7482021-02-04
  • Java教程Java實(shí)現(xiàn)搶紅包功能

    Java實(shí)現(xiàn)搶紅包功能

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java BufferWriter寫文件寫不進(jìn)去或缺失數(shù)據(jù)的解決

    Java BufferWriter寫文件寫不進(jìn)去或缺失數(shù)據(jù)的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進(jìn)去或缺失數(shù)據(jù)的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
主站蜘蛛池模板: 午夜伦伦电影理论片费看 | 欧美同性猛男野外gay免费 | 亚洲高清无在码在线电影 | 91影视永久福利免费观看 | 成人青青草| 国产专区一va亚洲v天堂 | 美女逼逼软件 | 欧美夫妇野外交换hd高清版 | 2021国产麻豆剧传媒剧情动漫 | 久久re这里精品在线视频7 | 亚洲欧美成人中文在线网站 | 日韩精品欧美国产精品亚 | 国产aaa毛片 | 三级视频中文字幕 | 扒开双腿疯狂进出爽爽动态图 | 1313午夜精品理伦片 | 四虎海外影院 | 日韩成人小视频 | 国产一区二区在线观看视频 | 欧美日本道免费一区二区三区 | 白丝美女用胸伺候主人 | 国产成人精品视频午夜 | 日韩欧美国产免费看清风阁 | 美女裆部 | 亚洲成a人片777777久久 | 臀控福利大臀的网站 | 日韩欧美国产一区二区三区 | 2020国语对白露脸 | 国产成人小视频在线观看 | 性一交一乱一伧老太 | www.青青操| 午夜在线观看免费完整直播网 | 天天做天天爱天天爽综合区 | 欧美日韩中文字幕久久伊人 | 男人和女人日比 | 校花被扒开尿口折磨憋尿 | 91麻豆精品国产自产在线 | 日韩在线二区 | 成年无限观看onlyfans | 精品久久综合一区二区 | 晓雪老师我要进你里面好爽 |