Java große integer?

7 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Ein normaler Integer hat nur 32-bit und kann damit nur bis max. 2^31 - 1 rechnen (2.147.483.647).

In Java gäbe es auch noch Long, welcher bis zu 64-bit halten kann (2^63 - 1, also 9.223.372.036.854.775.807).

Für alles, was darüber geht, muss ein BigInt verwendet werden (bzw. BigDecimal bei Gleitkommazahlen).

Woher ich das weiß:Berufserfahrung – Inhaber einer App-Agentur & 15+ Jahre Programmiererfahrung

In Java selbst wird es dabei zu einem integer overflow kommen, Integer sind durch 2e31 beschränkt. Es gibt jetzt im wesentlichen zwei Möglichkeiten, solche Berechnungen in Java anzustellen:

1. Verwende die Klasse java.math.BigInteger

BigInteger ist eine Klasse, die mit Zahlen jenseits der Wertebereiche der primitiven Datentypen rechnen kann (analog für Gleitkommazahlen gibt es im selben Paket noch die Klasse BigDecimal). Definiere dir also zwei Variablen und verwende die Methoden der Klasse, dann erhältst du das Ergebnis 601:

BigInteger b = new BigInteger("5000");
BigInteger m = new BigInteger("999");
BigInteger res = b.pow(5000).mod(m);
System.out.println(res.toString()); // 601
2. Der mathematische Weg

Natürlich kann man alles mit der Brechstange lösen, aber einfacher werden die meisten Berechnungen meistens, wenn man ein paar mathematische Überlegungen anstellt. Was du hier machen möchtest, ist diskret zu exponentieren. Dafür existiert ein auch bei sehr großen Zahlen noch relativ effizientes Verfahren, nämlich der Square-and-multiply-Algorithmus (binäre Exponentiation):

https://de.wikipedia.org/wiki/Bin%C3%A4re_Exponentiation

Eine sehr schöne Erklärung dazu findest du hier:

https://www.youtube.com/watch?v=5FJ7NJH_y74

Letztlich kein Hexenwerk, aber um Längen effizienter als naive Multiplikation, weil man durch iteriertes modulo-rechnen die Anzahl an Multiplikationen enorm reduziert und zusätzlich in "humanen" Zahlenbereichen bleibt. Eine Implementierung habe ich mal aus einem eigenen Projekt in Python rausgezogen, lässt sich aber auch einfach auf Java übertragen:

def exponentiateModular(a: int, b: int, n: int) -> int:
    powersModN = [a] # a^k for each k <= b
    while 2 ** len(powersModN) <= b:
        powersModN.append(powersModN[-1] ** 2 % n)
    res = 1
    for i in range(log(b) // log(2) + 1):
        if b & (1 << i):
           res *= powersModN[i]
    return res % n

LG

Woher ich das weiß:Berufserfahrung – Software-Entwicklung

Man würde 5000^5000 nicht ausrechnen, wenn man das Ergebnis nur modulo 999 braucht.

Erstmal: Wie viele Stellen hätte 5000^5000? Das wären aufgerundet

log10 (5000^5000)
= 5000 * log10(5000)
= 5000 * log10(5 * 1000)
= 5000 * (3 + log10(5))

Jetzt ist log10(5) etwa 0.7, also hat die Zahl 5000 * 3.7 = 18500 Stellen.

Dann: Was ist 5000^5000 mod 999?

Also, erstmal kann man das mit ein wenig Übung recht elementar mit Hand ausrechnen; das Ergebnis ist 601.

Das das aber eine Programmieraufgabe ist, würde ich mir einen Algorithmus bauen:

1) Initialisier den integer x mit 1. Initialisiere n mit 5000

2) Multiplizieren x mit 5000, ziehe von n eins ab.

2) Ziehe von x so lange 999 ab, bis x < 999. Alternativ kannst du das mit einer Integer-Division und Multiplikation machen.

3) Wenn n > 0, dann bei 2) weiter. Wenn n = 0, dann steht in x das Ergebnis.

Dafür braucht man keine großen Zahlen, die maximale Zahl, die hier vorkommen kann, ist 998 * 5000.

Woher ich das weiß:Studium / Ausbildung – Studium und Promotion in Angewandter Mathematik

In deinem Fall würde ich wahrscheinlich folgendes machen (ungetestet):

int result = new BigInteger("5000").pow(5000).mod(new BigInteger("999")).intValue();
Woher ich das weiß:Hobby