initial commit
This commit is contained in:
3
src/META-INF/MANIFEST.MF
Normal file
3
src/META-INF/MANIFEST.MF
Normal file
@@ -0,0 +1,3 @@
|
||||
Manifest-Version: 1.0
|
||||
Main-Class: de.sebse.karatsubabiginteger.Main
|
||||
|
||||
180
src/de/sebse/karatsubabiginteger/Main.java
Normal file
180
src/de/sebse/karatsubabiginteger/Main.java
Normal file
@@ -0,0 +1,180 @@
|
||||
package de.sebse.karatsubabiginteger;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Main {
|
||||
static final int LONG_SHIFT = (int) Math.pow(10, (int) Math.log10(Long.MAX_VALUE)/2-1);
|
||||
//100000000, Die etwas weniger als die Hälfte eines Long als 10er Potenz
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
//main für Zeittest
|
||||
/*long zeit=0;
|
||||
long z=0;
|
||||
for (int i=0;i<100;i++){
|
||||
z=testTime(9000);
|
||||
System.out.println(z+ " Millisek.");
|
||||
zeit=zeit+ z;
|
||||
System.out.println("i:"+i);
|
||||
}
|
||||
System.out.println(((long) zeit/100)+ " Millisek.");*/
|
||||
|
||||
|
||||
|
||||
//main für eingabe über die Console
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
System.out.println("Number 1: ");
|
||||
BigInteger a = scanner.nextBigInteger();
|
||||
System.out.println("Number 2: ");
|
||||
BigInteger b = scanner.nextBigInteger();
|
||||
|
||||
System.out.println("Ergebnis der BigInteger Multiplikation:");
|
||||
System.out.println(a.multiply(b));
|
||||
System.out.println("Ergebnis der karatsuba Multiplikation:");
|
||||
System.out.println(karatsubaMultiplication(a, b));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static Long testTime(int n){//Funktion zum zeitmessen wie lange an einer Multiplikation gerechnet wird
|
||||
String zufallszahl = "";
|
||||
for (int i=0; i<n/10;i++){//Zufallszahlen erzeugen
|
||||
zufallszahl=zufallszahl + String.valueOf((int) (Math.random()*Math.pow(10,17)));
|
||||
}
|
||||
BigInteger a = new BigInteger(zufallszahl);
|
||||
zufallszahl = "";
|
||||
for (int i=0; i<n/10;i++){
|
||||
zufallszahl=zufallszahl + String.valueOf((int) (Math.random()*Math.pow(10,17)));
|
||||
}
|
||||
BigInteger b = new BigInteger(zufallszahl);
|
||||
System.out.println(zufallszahl.length());
|
||||
split(a);
|
||||
split(b);
|
||||
|
||||
final long timeStart = System.currentTimeMillis();
|
||||
System.out.println(karatsubaMultiplication(a, b));
|
||||
final long timeEnd = System.currentTimeMillis();
|
||||
return timeEnd - timeStart;
|
||||
}
|
||||
|
||||
|
||||
private static BigInteger karatsubaMultiplication(BigInteger a, BigInteger b) {//Muss für die Karatsuba-Multiplikation aufgerufen werden (main)
|
||||
List<Long> lista = split(a);
|
||||
List<Long> listb = split(b);
|
||||
return merge(multiply(lista, listb, 0, 0, listb.size()));
|
||||
}
|
||||
|
||||
private static List<Long> multiply(List<Long> a, List<Long> b, long startA, long startB, long len) {//rekusiver Karatsuba-Algorithmus
|
||||
if (a.size()!=a.size())
|
||||
throw new IllegalArgumentException();
|
||||
// size(a) have to equals size(b)
|
||||
if (len==1) {
|
||||
List<Long> ret = new ArrayList<>(); // size(ret) in {1, 2}
|
||||
long value = a.get((int) startA)*b.get((int) startB);
|
||||
long carry = value / LONG_SHIFT;
|
||||
ret.add(value % LONG_SHIFT);
|
||||
if (carry != 0)
|
||||
ret.add(carry);
|
||||
return ret;
|
||||
} else {
|
||||
long endA = startA+len;
|
||||
long endB = startB+len;
|
||||
long midA = startA+len/2;
|
||||
long midB = startB+len/2;
|
||||
|
||||
// A-low + A-high
|
||||
List<Long> addA = add(a.subList((int) startA, (int) midA), a.subList((int) midA, (int) endA));
|
||||
// B-low + B-high
|
||||
List<Long> addB = add(b.subList((int) startB, (int) midB), b.subList((int) midB, (int) endB));
|
||||
|
||||
while (addA.size()>addB.size())
|
||||
addB.add((long) 0);
|
||||
while (addB.size()>addA.size())
|
||||
addA.add((long) 0);
|
||||
|
||||
List<Long> retC = multiply(addA, addB, 0, 0, addA.size());
|
||||
|
||||
// A-low * B-low
|
||||
List<Long> retA = multiply(a, b, startA, startB, midA-startA);
|
||||
// A-high * B-high
|
||||
List<Long> retB = multiply(a, b, midA, midB, len-(midA-startA));
|
||||
|
||||
retC = sub(retC, add(retA, retB));
|
||||
return add(add(retB, retC, len/2), retA, len/2);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Long> sub(List<Long> a, List<Long> b) {//Subtrahieren zweier long[]
|
||||
// if b smaller than a
|
||||
for (int i = 0; i < b.size(); i++) {
|
||||
b.set(i, -b.get(i));
|
||||
}
|
||||
return add(a, b);
|
||||
}
|
||||
|
||||
private static List<Long> add(List<Long> a, List<Long> b) {
|
||||
return add(a, b, 0);
|
||||
}
|
||||
|
||||
private static List<Long> add(List<Long> a, List<Long> b, long shiftA) {//Addieren zweier Long[],
|
||||
// a kann noch mit shiftA verschoben werden und die Zahlen können unterschiedlich lang sein
|
||||
List<Long> ret = new ArrayList<>();
|
||||
long offsetB = 0;
|
||||
for (; offsetB < shiftA; offsetB++) {
|
||||
if (offsetB>=b.size())
|
||||
ret.add((long) 0);
|
||||
else
|
||||
ret.add(b.get((int) offsetB));
|
||||
}
|
||||
long offsetA = 0;
|
||||
long carry = 0;
|
||||
// a[i]+b[i]
|
||||
for (; offsetB < b.size() && offsetA < a.size(); offsetB++, offsetA++) {
|
||||
long value = b.get((int) offsetB)+a.get((int) offsetA)+carry;
|
||||
carry = value / LONG_SHIFT;
|
||||
ret.add(value % LONG_SHIFT);
|
||||
}
|
||||
// b ist länger als a
|
||||
for (; offsetB < b.size(); offsetB++) {
|
||||
long value = b.get((int) offsetB)+carry;
|
||||
carry = value / LONG_SHIFT;
|
||||
ret.add(value % LONG_SHIFT);
|
||||
}
|
||||
// a ist länger als b
|
||||
for (; offsetA < a.size(); offsetA++) {
|
||||
long value = a.get((int) offsetA)+carry;
|
||||
carry = value / LONG_SHIFT;
|
||||
ret.add(value % LONG_SHIFT);
|
||||
}
|
||||
// Evtl. zusätzliche Stelle durch Übertrag
|
||||
if (carry != 0)
|
||||
ret.add(carry);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static List<Long> split(BigInteger a) {//spaltet ein BigInteger in ein Long ArrayList auf
|
||||
BigInteger b = BigInteger.valueOf(LONG_SHIFT);
|
||||
List<Long> list = new ArrayList<>();
|
||||
//noinspection ComparatorResultComparison
|
||||
while (a.compareTo(b) != -1) {
|
||||
list.add(a.mod(b).longValue());
|
||||
a = a.divide(b);
|
||||
}
|
||||
list.add(a.longValueExact());
|
||||
return list;
|
||||
}
|
||||
|
||||
private static BigInteger merge(List<Long> list) {//Ergebnis zusammen fügen
|
||||
BigInteger result = new BigInteger("0");
|
||||
int count = 0;
|
||||
for (Long val: list) {
|
||||
result = result.add(BigInteger.valueOf(val).multiply(BigInteger.valueOf(LONG_SHIFT).pow(count)));
|
||||
count++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user