2016-01-25 6 views
11

Gibt es eine Alternative für die Verwendung von BigInteger in Java?Java BigInteger Alternative

Wenn Sie führen den Betrieb auf BigInteger es führen immer wieder mit neuen BigInteger erstellt. Gibt es eine alternative Implementierung, bei der das Ergebnis einer Operation zwischen zwei großen Ganzzahlen in einer davon gespeichert wird?

Zum Beispiel in Java, wenn Sie zwei große Ganzzahlen multiplizieren: a * b ein neues BigInteger ist erstellt, um das Ergebnis zu hosten. Ich möchte das Ergebnis in a speichern.

Ich möchte dies, um die Leistung in einigen der Fälle meines Algorithmus

+8

Sie tun es falsch. Wenn Sie die Leistung erhöhen möchten, verwenden Sie nicht "BigInteger" an erster Stelle. Was genau ist der Leistungsengpass, den Sie beheben möchten? – Tunaki

+0

Eine technische Antwort wäre, Ihre eigene Implementierung zu schreiben, aber was @Tunaki gesagt hat, ist wahrscheinlich besser. Wenn Sie 'BigInteger' so intensiv verwenden, dass es die Leistung beeinträchtigt, sollten Sie wahrscheinlich etwas anderes verwenden. Wenn Sie 'BigInteger' verwenden müssen, akzeptieren Sie den damit verbundenen Leistungseinbruch. – Gorbles

+0

Mit anderen Worten, Sie suchen nach einer Art von 'ModifyableBigInteger'? –

Antwort

7

Es gibt wandelbar „Versionen“ von BigInteger gibt (zum Beispiel: https://github.com/bwakell/Huldra) Oder Sie können Ihre eigene Rolle. Die Verwendung eines veränderbaren Objekts kann den Druck auf den GC reduzieren. Sie sollten Ihre Anwendung wirklich benchmarken, um zu sehen, ob sich dies lohnt.

+1

Eigentlich tat Java auch eine MutableBigInteger-Klasse, aber es wird nur intern verwendet. –

+0

Interessant - auch von BigInteger verwendet –

13

Ich bezweifle, dass die Leistung des Algorithmus zu erhöhen verbessern, wenn Sie irgendwie dies tun könnte, aber das Hauptprinzip ist, dass BigInteger ist unveränderlich. Sie können eine Operation nicht ausführen, ohne eine neue Instanz zu generieren, und es gibt gute Gründe für dieses Verhalten - wenn Sie nämlich mehrere Threads auf einer einzelnen BigInteger betreiben, können Sie sicher sein, dass diese Threads das BigInteger nicht direkt überschreiben *.

Wenn Sie dieses Verhalten nicht wünschen, Ihre einzige Option ist es, eine neue Klasse zu erstellen, aber beachten Sie, dass Sie immer noch mit der Unveränderlichkeit der BigInteger s bei einig Schicht tun werden.

*: Weißt du, so lange wie du bist nicht Neuzuweisung die Variable ...

+0

"Sie werden sich immer noch mit der Unveränderlichkeit von BigIntegers in irgendeiner Schicht befassen." - Oder Sie könnten große Ganzzahlen von Grund auf neu implementieren (yuck). –

+0

@JanDvorak: Warum das Rad neu erfinden? : P – Makoto

+0

@Makoto: Räder werden ständig neu erfunden. In diesem Fall würde man sehr wahrscheinlich die mutierbare BigInt-Klasse, die man braucht, bekommen. ;-) Tatsache ist, dass es getan werden kann, ohne sich mit der unveränderlichen Natur von BigInteger zu beschäftigen. –

4

Was Sie fordern ist unwahrscheinlich, dass in keiner Weise mehr performant außer wenn alles, was Sie wollen zu tun ist hinzuzufügen. Der Grund dafür ist, dass die Anzahl der Bits im Ergebnis fast jeder mathematischen Operation (außer der oben genannten add) eine andere Größe als die ursprüngliche Zahl ist. Sie werden fast immer müssen eine neue Nummer der Ergebnisse zuweisen und kopieren Sie es wieder über das Original, so alles, was Sie tatsächlich tun, macht es langsamer.

Wenn Sie jedoch nur/sub hinzufügen müssen, ist dies machbar und könnte tatsächlich ein wenig schneller sein, da es keine Zuweisung des neuen Arrays zum Hinzufügen gibt.

Fast alle anderen Funktionen wären besser an die BigInteger-Klasse delegiert.

class MutableBigInteger { 
    BigInteger n; 

    public MutableBigInteger add (MutableBigInteger n) { 
     this.n = this.n.add(n.n); 
     return this; 
    } 
} 
+0

Dies gilt nur unter der Annahme, dass Sie nur eine Operation ausführen, aber betrachten Sie das nächste Beispiel: a * b/c * d und es wird komplizierter. Dies ermöglicht mir auch, meinen BigInteger für zukünftige Operationen wiederzuverwenden. –

+1

Wenn die höchsten Lins hinzugefügt werden, muss das Array 1 Glied größer als die Originale sein. Außerdem haben zwei verschiedene Werte oft nicht die gleiche Größe, so dass eine Neuzuweisung oft auch bei Addition oder Subtraktion stattfinden muss. –

+0

Die Benchmarks bei [Huldra] (https://github.com/bwakell/Huldra) scheinen mit dir nicht übereinzustimmen. Ich frage mich, wie diese Benchmarks gegen Java 8 BigInteger –