Julia: Int versus Int8 versus Int64

8

Angenommen, ich habe eine Ganzzahl n , die nur Werte in [0, 10] annehmen wird. Sollte ich es als n::Int deklarieren, um allgemein zu sein, als n::Int8 oder n::UInt8 , um sparsam zu sein oder n::Int64 für ein 64-Bit-System?

Bitte klären Sie die Gründe für einen Neuling, z. Stil, Leistung.

Hintergrund: Ich versuche Julia zu lernen und verirre mich schnell bei Wörtern wie type , immutable , syntactic sugar ! Ich glaube, ich habe das gelesen: https://docs.julialang.org/en/release-0.5/manual/integers-and-floating-point-numbers/

    
PatrickT 08.06.2017, 12:25
quelle

2 Antworten

8

Es ist wichtig, zwei verschiedene Fälle zu unterscheiden.

Speicher: Wenn Sie einen Typ haben, der n als eines seiner Felder oder als Wert in einem Array speichert, sollten Sie definitiv Int8 oder UInt8 verwenden. Selbst wenn der gespeicherte Speicherplatz für einen einzelnen Wert vernachlässigbar ist, können, wenn viele Instanzen Ihres Typs in einer Sammlung erstellt und gespeichert werden, die Platzeinsparungen schnell erheblich werden. Angenommen, Sie haben einen Foo -Typ mit einem Feld n , dann könnten Sie dies tun:

%Vor%

Wenn ein Wert dem n -Feld eines Foo -Objekts zugewiesen wird, wird es automatisch in UInt8 konvertiert und ein Fehler wird ausgelöst, wenn der Wert nicht korrekt konvertiert werden kann:

%Vor%

Wenn der Wert, der zugewiesen wird, bereits vom richtigen Typ ist, ist keine Überprüfung erforderlich, so dass kein Overhead entsteht.

Dispatch: Wenn Sie eine Methode einer Funktion schreiben, die n als Argument verwendet, dann ist es nicht schädlich, wenn Sie eine lose Typ-Annotation für das Argument n haben, da dies sinnvoll ist semantisch. In dem Fall, den Sie beschrieben haben, scheint es, dass jede Art von Integer-Wert sinnvoll wäre, so dass die Verwendung von n::Integer wahrscheinlich angemessen wäre. Wenn Sie beispielsweise einen überprüften Konstruktor für Foo -Objekte implementieren möchten, können Sie Folgendes tun:

%Vor%

Nun wird ein Fehler ausgegeben, wenn ein Wert außerhalb von [0, 10] angegeben wird:

%Vor%

Diese Foo -Konstruktion funktioniert für jede Art von Ganzzahl, prüft, ob sie im richtigen Bereich ist und konvertiert dann in UInt8 . Dies ist etwas restriktiver als der eingebaute Konstruktor für Foo , der gerne irgendein -Argument des n -Arguments nimmt und versucht, es in UInt8 zu konvertieren - selbst wenn das Argument nicht ist eines Integer-Typs. Wenn diese Art von Verhalten wünschenswert ist, könnten Sie die Typensignatur hier weiter zu n::Real , n::Number (oder sogar n::Any , obwohl das übertrieben scheint) lösen.

Beachten Sie, dass es keinen Leistungsvorteil für eng typisierte Methodenargumente gibt - der spezialisierte Code für tatsächliche Argumenttypen wird trotzdem auf Anforderung generiert.

    
StefanKarpinski 08.06.2017, 21:42
quelle
3

BEARBEITEN: beziehen Sie sich auf Stefans akzeptierte Antwort. Ich meine, dies ist eine Antwort auf die Verwendung von Typen in der Funktion Versand, aber in Wirklichkeit widersprach ich (wie ich explizit sage, dass Funktion Versand eigentlich Integer sein sollte).

Ich würde immer Int verwenden, nur für die Allgemeinheit, aber es hängt davon ab, wie leistungsfähig Ihre Anwendung ist. Niemals Int64 , es sei denn, du benötigst es explizit. Viele Funktionen versenden auf Int anstatt Integer (obwohl die Empfehlung ist, nach abstrakten Typen zu versenden), was bedeutet, dass sie beim Übergeben eines UInt8 fehlschlagen (weil Int ein Subtyp von Signed und UInt ist) ist nicht) so übereifrig mit Typen wird Probleme verursachen. Als allgemeine Faustregel sollten Sie nie spezifischer mit Typen sein als Sie müssen.

    
Michael K. Borregaard 08.06.2017 12:33
quelle

Tags und Links