-
Notifications
You must be signed in to change notification settings - Fork 0
/
BigInt.java
136 lines (117 loc) · 4.18 KB
/
BigInt.java
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
package self.math;
import java.util.Iterator;
public interface BigInt extends Comparable<BigInt>, Iterable<Integer> {
/**
* restituisce il valore del BigInt sottoforma di stringa di caratteri
* @return rappresentazione del valore come stringa
*/
String value();
/**
* @returns numero di cifre del BigInt this
*/
default int length() {
Iterator<Integer> it = this.iterator();
int cont = 0;
for (; it.hasNext(); it.next()) cont++;
return cont;
}
/**
* restituiscce una nuova istanza di BigInt con le stesse cifre di x
* @param x intero da cui costruire il BigInt
* @returns nuova istanza di BigInt
*/
BigInt factory( int x );
/**
* @returns una nuova istanza di BigInt con valore aumentato di 1 rispetto a this
*/
BigInt incr();
/**
* @returns una nuova istanza di BigInt con valore ridotto di 1 rispetto a this
* @throws IllegalStateException nel caso in cui il BigInt abbia già il valore minimo 0
*/
BigInt decr() throws IllegalStateException;
/**
* @param a secondo termine della somma tra BigInt (this + a)
* @returns nuovo BigInt risultato della somma
*/
default BigInt add( BigInt a ) {
BigInt result = this;
final BigInt bigZero = factory(0);
for (int currentState = 1; currentState > 0 ;
currentState = a.compareTo(bigZero)) { // start comparing to the end
result = result.incr();
a = a.decr();
}
return result;
}
/**
* @param s secondo termine della differenza tra BigInt (this - s)
* @returns nuovo BigInt risultato della differenza
* @throws IllegalArgumentException nel caso in cui il secondo termine della differenza sia maggiore del primo (atteso this >= s)
*/
default BigInt sub( BigInt s ) {
if (this.compareTo(s) < 0) throw new IllegalArgumentException();
final BigInt bigZero = factory(0);
BigInt result = this;
for (int currentState = 1; currentState > 0 ;
currentState = s.compareTo(bigZero)) {
result = result.decr();
s = s.decr();
}
return result;
}
/**
* @param a secondo termine del prodotto tra BigInt (this * a)
* @returns nuovo BigInt risultato del prodotto
*/
default BigInt mul( BigInt m ) {
BigInt result = factory(0);
final BigInt bigZero = factory(0);
for (int currentState = 1; currentState > 0 ;
currentState = m.compareTo(bigZero)) {
result = result.add(this);
m = m.decr();
}
return result;
}
/**
* @param d secondo termine della divisione intera tra BigInt (this / d)
* @returns nuovo BigInt risultato della divisione intera
* @throws IllegalArgumentException nel caso in cui il divisore sia maggiore del primo (atteso this >= d)
*/
default BigInt div( BigInt d ) {
if (this.compareTo(d) < 0) throw new IllegalArgumentException();
BigInt result = factory(0);
BigInt dividendo = this;
for (int currentState = 1; currentState > 0 ;
currentState = dividendo.compareTo(d)) {
dividendo = dividendo.sub(d);
result = result.incr();
}
return result;
}
/**
* esegue la divisione intera e poi ne calcola il resto eseguendo la differenza tra il dividendo e il quoziente (this - (this / d))
* @param d secondo termine della divisione intera tra BigInt (this / d)
* @returns nuovo BigInt resto della divisione intera
* @throws IllegalArgumentException nel caso in cui il divisore sia maggiore del primo (atteso this >= d), eccezione ereditata da div()
*/
default BigInt rem( BigInt d ) throws IllegalArgumentException {
BigInt quoziente = this.div(d);
BigInt result = this.sub(quoziente.mul(d));
return result;
}
/**
* @param exponent esponente della potenza (this^exponent)
* @returns nuovo BigInt risultato della potenza
*/
default BigInt pow( int exponent ) {
BigInt result = factory(1);
BigInt bigZero = factory(0);
for (BigInt cont = factory(exponent); cont.compareTo(bigZero) > 0; ) {
result = result.mul(this);
cont = cont.decr();
}
return result;
};
}