2016-07-07 20 views
3

Ich versuche, ein Array von BigIntegers zu erstellen, aber es scheint, dass das Array von ganzen Zahlen indiziert werden muss (und wenn das wahr ist, scheint das extrem dumm zu sein, aber ich ' Ich hoffe, ich verstehe nur etwas falsch. Was ich versuche ist die im Wesentlichen die folgenden:Wie man ein Array von BigIntegern durch BigIntegers indiziert

BigInteger totalChoiceFunctions = BigInteger.valueOf(50031545098999704); 
BigInteger[][] choiceFunctions = new BigInteger[totalChoiceFunctions][36]; 

Aber dies bewirkt, dass die Fehlermeldung „Typenkonflikt: kann nicht von BigInteger konvertieren int“. Um dies zu beheben, habe ich versucht:

BigInteger[][] choiceFunctions = new BigInteger[totalChoiceFunctions.intValue()][36]; 

jedoch scheint dies nicht zu helfen. Wenn ich kompilieren und laufen erhalte ich den Laufzeitfehler von:

exception in thread 'main' java.lang.NegativeArraySizeException 

Verwirrt schaute ich auf die Oracle-Dokumentation für die intValue() -Methode von BigInteger und festgestellt, dass „wenn diese BigInteger zu groß ist in einem int zu passen Es werden nur die niederwertigen 32 Bits zurückgegeben. Beachten Sie, dass diese Konvertierung Informationen über die Gesamtgröße des BigInteger-Werts sowie ein Ergebnis mit dem umgekehrten Vorzeichen verlieren kann ". Ich vermute, das ist, was passiert, wenn man bedenkt, dass 50031545098999704 sicherlich zu groß für int ist (und warum ich mich einem Array von BigIntegers zugewandt habe, da ich mein Array mit den Zahlen von 1 bis 50031545098999704 indexieren lassen möchte).

Wenn mein Verständnis richtig ist, dann:

BigInteger[][] chioceFunctions = new BigInteger[totalChoiceFunctions][36]; 

erzeugt ein Array, das speichert BigIntegers ist aber immer noch indiziert von ints. Wie kann ich ein Array erstellen, das von BigIntegers sowohl gespeichert als auch indiziert wird? Ist es möglich? Beachten Sie, dass der Code, den ich dafür verwende, in diesem Fall funktionieren kann, wenn ich Longs anstelle von Ints zum Indexieren verwende, aber ich möchte, dass er auf eine Größe skaliert, bei der ich von BigIntegers indexiert werden muss. Fehle ich etwas Offensichtliches?

+0

Ich bin neugierig, warum das dumm scheint? Der Wert Ihres Index bestimmt nur die Nummer des Objekts, das Sie speichern können. Wenn Sie mehr speichern müssen, erstellen Sie Ihren eigenen Container ... – ChrisCM

+3

Auch wenn Sie die Grenzen von Java-Arrays ignorieren, haben Sie nicht den Speicher für ein Array von 50 Billiarden mal 36 BigIntegern. – user2357112

+1

Gee ow viel Speicher haben Sie brauchen mindestens '50031545098999704 * 64 * 36' –

Antwort

4

Arrays in Java sind nicht spärlich, so würde das Array etwa 200 000 Terabyte brauchen (ohne die referenzierten Arrays/BigIntegers). Also nein, momentan nicht möglich. Es gibt einige Pläne, die lange als Index in Arrays mit vielleicht Java 10 (sicherlich nicht Java9) zu unterstützen.

Ich vermute, dass Sie tatsächlich eine spärliche Datenstruktur wollen; a Map < BigInteger, BigInteger> oder wie Sie ein verschachteltes Array haben Karte < Tuple < BigInteger, Integer>, BigInteger> sollte für Sie arbeiten.

2

Nein, das ist nicht möglich. In Java werden alle Arrays nur durch Ganzzahlen indiziert.

+0

Dies zu verbessern, da dies eine richtige Antwort ist. :). –

2

In der Theorie (aber nicht praktisch) können Sie eine solche Klasse erstellen.

Ein gewöhnliches Array kann seine Größe nicht dynamisch vergrößern, oder? Aber ArrayList kann! Wie kann es das tun? Nun, indem Sie ein neues Array mit einer größeren Größe neu erstellen, wenn die Kapazität voll ist.

Sie können hier die gleiche Logik anwenden.

Ein gewöhnliches Array kann keine 50031545098999704 Elemente enthalten. Aber können Sie mehrere Arrays erstellen, um sie zu halten!

So in Ihrer Klasse, sollten Sie eine Matrix haben:

public class BigIntegerArray<T> { 
    private T[][] innerMatrix; 
} 

Der Konstruktor eine Zahl als Feldlänge annehmen wird, nicht wahr? Mit der Array-Länge wissen Sie, wie viele Arrays Sie benötigen. Wenn zum Beispiel die Größe Array N wo Integer.MAX_VALUE < N <= Integer.MAX_VALUE * 2, wissen Sie, dass Sie die innere Matrix wie folgt initialisieren sollte:

innerMatrix = new T[2][Integer.MAX_VALUE]; 

einfach ein paar Mathe verwenden!

Und Sie möchten eine get und set Methode implementieren. Wenn der Index größer als Integer.MAX_VALUE ist, aber kleiner als oder gleich Integer.MAX_VALUE * 2, greifen sie wie folgt aus:

innerArray[1][index - Integer.MAX_VALUE]; // not real code. I'm just illustrating the point. 

Sie bekommen, was ich meine? Es ist im Grunde einfache Mathematik.

EDIT:

Vielleicht habe ich diese gut genug, um nicht erklären. Der Algorithmus, der die Schaffung der inneren Matrix ist wie folgt: (Pseudocode)

if arraySize is smaller than Integer.MAX_VALUE then 
    create an array of size arraySize 
    return 
initialize a variable counter to 0 
while arraySize > 0 
    subtract Integer.MAX_VALUE from arraySize 
    increment counter 
create an array with the array size of counter 

Der Zugriff Teil ist ähnlich:

if index is smaller than Integer.MAX_VALUE then 
    access [0][index] 
    return 
initialize a variable counter to 0 
while arraySize > 0 
    subtract Integer.MAX_VALUE from arraySize 
    increment counter 
access [counter][index - Integer.MAX_VALUE * counter] 
1

Java lässt Sie nur Index von int der maximale Index, den Sie erreichen können, ist Integer.MAX_VALUE, die 1 Byte kurz von 2 GB ist, die 2147483647 ist. Ihr Array kann keine Zahlen größer als diese enthalten.

Sie sollten eine Datenstruktur verwenden, die mehr als int Grenzen, z. maps. Maps werden ohne Limit wie ein 2D Array nur verhalten, hier können Sie speichern sie als: -

Map m = new HashMap<BigInteger,BigInteger>(); 

Das Einfügen und Abrufen ein wenig härter im Vergleich wird auf einfache 2D array aber die Grenzen der Indizes unter Berücksichtigung nur int wir mit muss mit einem anderen Ansatz gehen.