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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
| // 导入对应模块
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class BigNum {
/**
* 此方法用于快速创建一个存储有多精度整数的ArrayList对象
* 参数 elements 为整个整数的每一位数字
* 返回 ArrayList<Integer>
*/
public static ArrayList<Integer> createArrayList(int ... elements) {
ArrayList<Integer> list = new ArrayList<Integer>();
for (Integer element : elements) {
list.add(element);
}
return list;
}
/**
* 此方法用于比较两个数的大小。若第一个数大于等于第二个数则返回true,否则返回false
* 参数 num1, num2 为要比较的数
* 返回比较结果 boolean
*/
public static boolean isBigger(ArrayList<Integer> num1, ArrayList<Integer> num2) {
if(num1.size() < num2.size()) return false;
else if(num1.size() > num2.size()) return true;
else if(num1.size() == num2.size()){
for (int i = 0; i < num1.size(); i++){
if(num1.get(i)<num2.get(i)) return false;
else if(num1.get(i)>num2.get(i)) return true;
}
}
return true;
}
/**
* 此方法用于实现两个多精度整数相加
* 参数 num1, num2 为两个加数
* 返回存储有运算结果的 ArrayList<Integer>
*/
public static ArrayList<Integer> bigPlus (ArrayList<Integer> num1, ArrayList<Integer> num2){
// 判断特殊情况
if(num1.size() < num2.size()){
ArrayList<Integer> tmp = num1;
num1 = num2;
num2 = tmp;
}
if(num1.isEmpty()) return num2;
if(num2.isEmpty()) return num1;
//数组索引反向,使数字的位数与索引对齐
Collections.reverse(num1);
Collections.reverse(num2);
ArrayList result = new ArrayList(num1.size()+1); //创建结果对象
int c = 0; //进位值
for (int i = 0; i < num2.size(); i++){
//判断是否进位
if (num1.get(i) + num2.get(i) + c < 10){
result.add(num1.get(i) + num2.get(i) + c);
c = 0;
}else{
result.add(num1.get(i) + num2.get(i) + c - 10);
c = 1;
}
}
if(num1.size() == num2.size()) result.add(c); //若两数位数相等,则最高位直接为进位值
else{ //若两数位数不相等,把位数大的数的后续位直接与进位值相加,添加到结果中
result.add(c+num1.get(num2.size()));
for(int i : num1.subList(num2.size()+1,num1.size())){
result.add(i);
}
}
//把所有ArrayList的索引反向至正常状态
Collections.reverse(result);
Collections.reverse(num1);
Collections.reverse(num2);
//消除前导0
if((int)result.get(0) == 0) {
result.remove(0);
}
return result;
}
/**
* 此方法用于实现两个多精度整数相减,若被减数小于减数则自动将两者调换后相减
* 参数 num1 为被减数, num2 为减数
* 返回存储有运算结果的 ArrayList<Integer>
*/
public static ArrayList<Integer> bigSub (ArrayList<Integer> num1, ArrayList<Integer> num2){
// 判断特殊情况
if(num1 == num2 || (num1.isEmpty() && num2.isEmpty())) return createArrayList(0);
if(num1.isEmpty()) return num2;
if(num2.isEmpty()) return num1;
if(!BigNum.isBigger(num1,num2)){
System.out.println("检测到减数大于被减数,已自动将减数与被减数交换");
ArrayList<Integer> tmp = num1;
num1 = num2;
num2 = tmp;
}
//数组索引反向,使数字的位数与索引对齐
Collections.reverse(num1);
Collections.reverse(num2);
ArrayList result = new ArrayList(num1.size()); //创建结果对象
int c = 0; //借位值
for (int i = 0; i<num2.size();i++){
//判断是否借位
if(num1.get(i) - num2.get(i) + c >= 0){
result.add(num1.get(i) - num2.get(i) + c);
c = 0;
}else{
result.add(num1.get(i) - num2.get(i) + c + 10);
c = -1;
}
}
//若两数位数不相等,把位数大的数的后续位直接与进位值相加,添加到结果中
if(num1.size() > num2.size()){
result.add(c+num1.get(num2.size()));
for(int i : num1.subList(num2.size()+1,num1.size())) result.add(i);
}
//把所有ArrayList的索引反向至正常状态
Collections.reverse(result);
Collections.reverse(num1);
Collections.reverse(num2);
//消除前导0
if((int)result.get(0) == 0) {
result.remove(0);
}
return result;
}
/**
* 此方法用于实现两个多精度整数相乘
* 参数 num1, num2 为两个乘数
* 返回存储有运算结果的 ArrayList<Integer>
*/
public static ArrayList<Integer> bigMult (ArrayList<Integer> num1, ArrayList<Integer> num2){
//数组索引反向,使数字的位数与索引对齐
if(num1.hashCode()==num2.hashCode()){
Collections.reverse(num1);
}else{
Collections.reverse(num1);
Collections.reverse(num2);
}
ArrayList result = new ArrayList(num1.size()+num2.size()); //创建结果对象
int uv = 0; //乘法临时值
for (int i = 0; i<num1.size()+num2.size()+1; i++) result.add(0); //结果所有位置为0
for (int i = 0; i<num1.size(); i++){
int c = 0; //进位值
for (int j = 0; j<num2.size(); j++){
uv = (int)result.get(i+j) + num1.get(i) * num2.get(j) + c; //按手工计算的方式进行逐位的运算
result.set(i+j, uv%10);
c = uv/10;
}
result.set(i+num2.size(), uv/10);
}
//把所有ArrayList的索引反向至正常状态
Collections.reverse(result);
if(num1.hashCode()==num2.hashCode()){
Collections.reverse(num1);
}else{
Collections.reverse(num1);
Collections.reverse(num2);
}
//消除前导0
while((int)result.get(0) == 0) {
result.remove(0);
}
return result;
}
/**
* 此方法用于实现两个多精度整数相除
* 参数 num1 为被除数, num2 为除数
* 返回存储有运算结果的 List<ArrayList<Integer>>, List 中第一项为商,第二项为余数
* @return
*/
public static List bigDiv (ArrayList<Integer> num1, ArrayList<Integer> num2){
if(num1 == num2) { //若两数相等,返回商为1,余数为0
return Arrays.asList(createArrayList(1),createArrayList(0));
}
if(num2.get(0) == 0 && num2.size() == 1){ //若除数为0,返回-1
System.out.println("除数不得为0");
return Arrays.asList(createArrayList(-1),createArrayList(0));
}
if(!BigNum.isBigger(num1,num2)){ //若除数大于被除数,则商为0,余数为被除数的值
return Arrays.asList(createArrayList(0),num1);
}
while(num1.get(0)==0){ //消除产生的前导0
num1.remove(0);
}
while(num2.get(0)==0){ //消除产生的前导0
num2.remove(0);
}
//创建并初始化结果对象
ArrayList result = new ArrayList();
for (int i=0;i<num1.size()-num2.size()+1;i++){
result.add(i,0);
}
//为除数扩充0至位数与被除数相等,并计算扩大的倍数
ArrayList num2_duiqi = (ArrayList) num2.clone();
int mult_times = 0; //扩大倍数
int times = 0; //除法结果
while(num2_duiqi.size()!=num1.size()){
num2_duiqi.add(0);
mult_times++;
}
while(true) {
while (BigNum.isBigger(num1, num2_duiqi)) { //逐次相减,并在结果中乘以对应的倍数
num1 = BigNum.bigSub(num1, num2_duiqi);
if(num1.size()!=0){
while(num1.get(0)==0){ //消除产生的前导0
num1.remove(0);
if(num1.isEmpty()){
break;
}
}
}
times++;
}
result.set(mult_times, times); //结果中填入结果
times = 0; //除法结果重置
//除完一轮重新对齐,并修改扩大的倍数
if ((int) num2_duiqi.get(num2_duiqi.size() - 1) == 0 && num2_duiqi.size() > num2.size()){
num2_duiqi.remove(num2_duiqi.size() - 1);
mult_times--;
}
else{ //除到末位后,将结果的索引反向
Collections.reverse(result);
break;
}
}
//返回结果
if(num1.size()==0){
return Arrays.asList(result,createArrayList(0));
}
return Arrays.asList(result,num1);
}
public static ArrayList bigPow (ArrayList<Integer> a, ArrayList<Integer> k, ArrayList<Integer> m){
ArrayList A = (ArrayList)a.clone(); //A=a
ArrayList b = createArrayList(1); //令b=1
if(k.isEmpty() || (k.size()==1 && k.get(0)==0)) return b; //如果k=0,则返回b
List kk;
ArrayList<Integer> k1 = (ArrayList<Integer>)k.clone();
ArrayList k2 = new ArrayList();
while(!(k1.size()==1&&k1.get(0)==0)){ //将k转换为二进制,结果为k2
kk = BigNum.bigDiv(k1,createArrayList(2));
k1 = (ArrayList<Integer>) kk.get(0);
k2.add(((ArrayList) kk.get(1)).get(0));
}
if((int)k2.get(0)==1){ //如果k0=1,则b=a
b= (ArrayList) a.clone();
}
for(int i = 1;i<k2.size();i++){
A = (ArrayList) BigNum.bigDiv(BigNum.bigMult(A,A), m).get(1);
if((int)k2.get(i)==1){
b = (ArrayList) BigNum.bigDiv(BigNum.bigMult(A,b), m).get(1);
}
}
return b;
}
}
|