"Größe" von Zahlen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Ich arbeite gerade an einem Parser für das "polygon file format" (http://paulbourke.net/dataformats/ply/), so weit funktioniert der auch ganz gut, jedoch würde ich gerne die Größe des Datentyps (z.B. float 4 byte, int 4 byte) mit der tatsächlichen Größe der Zahl vergleichen. Also "passt" Zahl x in n byte Speicher?
the more they change the more they stay the same
deets

Ich verstehe dein Problem nicht. Wenn du parst, dann musst du doch nur int(string) bzw. float(string) aufrufen - und das Ergebnis passt dann schon. Python kennt ja im Gegensatz zu C/Java keine Laengenbeschraenkung mehr bei ints (seit 2.4 oder so).

Oder willst du Daten *schreiben*? Dann musst du natuerlich aufpassen, da koennte dann das Modul struct hilfreich sein.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Vermisse auch irgendwie die Fragestellung.

Falls es Dir darum geht zu prüfen, ob eine Zahl noch von einem bestimmten Typen abgebildet werden kann:
Mit Integertypen kannst Du 2^(n*8) Werte für n Bytes darstellen. Für unsigned ist das auch Deine obere Grenze, für signed halbiert sich die obere Grenze.
Bei Floattypen wirds komplizierter. Hier müsstest Du prüfen, ob Deine vorliegende Zahl in Mantisse/Exponent zerlegt, noch in die Speichersegmente des Floattypen passt (also die Genauigkeit erhalten bleibt). Für 4 Byte-Floats sind die Mantisse 23 bittig und der Exponent 8 bittig (auf x86 Maschinen).
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Das Problem ist nicht Python, Python soll die .ply Datei nur parsen, eine D-lib, verwendet die Daten dann (in Form von JSON), ich dachte mir, dass das Überprüfen auf Größe hilfreich ist ;).

@jerch, das taugt mir eben nicht, ich müsste das für char, uchar, short, ushort, int, uint, float und double machen, ich dachte da liefert Python etwas nettest mit.

(Es handelt sich im übrigen um das Skript: https://bitbucket.org/dav1d/gljm/src/ff ... rse_ply.py, bitte main() ignorieren, das ist nur ein Platzhalter und wird atm nur zum Testen verwendet).
the more they change the more they stay the same
deets

Und wozu soll das dann gut sein? Entweder sind deine Daten in einem Wertebereich, den JSON schluckt - oder nicht. Falls die Fehlerbehandlung von D schlecht ist (sprich, es segfaultet), dann ok - aber dann musst du doch nur auf zwei Typen pruefen - float/double und int im Wertebereich von JSON.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Mir ist auch nicht klar, in wie fern Python hier Abhilfe schaffen soll, so es denn von Typenklauberei überhaupt keine Ahnung hat.

Kannst Du mal kurz erklären, was Python machen soll? Da es um D geht, sollest Du eher dort sicher stellen, dass Typen und Werte zueinander passen, sprich der Parser mit Bereichsprüfung ist da besser aufgehoben.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

Also gljm lädt eine JSON-Datei und arbeietet mit dieser. Das Python-Skript soll eine .ply-Datei in dieses JSON-Format bringen, soweit funktioniert das auch, allerdings würde ich gerne gleichzeitig mit dem Skript prüfen ob der angegebene Datentyp, dem Datentyp der Daten entspricht (property ushort bar), um Fehler so früh wie möglich zu finden, es soll eigentlich nur eine Hilfe sein, damit ich sichergehen kann, dass die JSON-Dateien korrekt sind.
the more they change the more they stay the same
deets

Nochmal: da bringt dir der Test auf Wertebereiche in PLY und dem Python-Parser doch nichts. Du musst wenn pruefen, ob die Wertebereiche, welche dann das JSON enthaelt, korrekt sind. Wenn das die serialisierende JSON-Bibliothek nicht fuer dich macht, dann kannst du das selbst machen - so denn die D-Bibliothek da bockig ist.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Für Integertypen gilt das oben Gesagte, Du musst Dir nur über die Bytegrößen und Vorzeichen der verschiedenen Typen in D im Klaren sein und kannst dann entsprechend testen.

Für float/double wirds schwieriger. Um das Problem zu vereinfachen, könntest Du es mit struct/ctypes einfach austesten und die Werte vergleichen (Achtung: Rundungsfehler können immernoch auftreten, z.B. könnte der PLY-Exporter versuchen, nicht signifikante Stellen zu runden):

Code: Alles auswählen

>>> from struct import *
>>> pack('f',1.23456789)
'R\x06\x9e?'
>>> unpack('f', 'R\x06\x9e?')
(1.2345678806304932,)
>>> pack('d',1.23456789)
'\x1b\xde\x83B\xca\xc0\xf3?'
>>> unpack('d', '\x1b\xde\x83B\xca\xc0\xf3?')
(1.23456789,)
>>> from ctypes import *
>>> c_float(1.23456789)
c_float(1.2345678806304932)
>>> c_float(1.23456789).value
1.2345678806304932
>>> c_double(1.23456789).value
1.23456789
Sowohl struct als auch ctypes gehen aber von C-Typen aus, k.A. ob sich D-Typen grundlegend unterscheiden.

NB: Um wirklich sicher zu gehen, das Deine Tests in Python die Typen in D abdecken, brauchst Du eine Art dtypes-Modul für Python, welches die Typprüfung übernimmt. Wie siehts in D mit Plattformabhängigkeit und Typen aus? Spätestens hier wirds gruselig, aus einer so hardwarefernen Sprache wie Python solche Fälle zu beachten und saubere Vorhersagen über das Verhalten in D treffen zu können. Was wiederum für die Typ-/Bereichsprüfung in D spricht...
Zu JSON: JSON ist spezifiziert und orientiert sich an ECMA/Javascript-Fähigkeiten. Daher sind Dir hier schon Grenzen gesetzt, die auch die D-Lib einhalten sollte.
0x1cedd1ce
User
Beiträge: 31
Registriert: Sonntag 3. Oktober 2010, 12:21

Wenn du in deinem D-Programm die Zahlen als Strings einliest und dann parst, brauchst du nicht überprüfen ob die "Größe" stimmt sondern lediglich ob die Zahl innerhalb des erlaubten Wertebereich liegt.
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

@deets: das ist mir klar, ich dachte nur, das wäre ein schönes Feauture (welches mir auch Neu-Kompelieren sparen würde, jaja ich bin faul ;))

Datentypen entsprechen denen in C (nur andere Bezeichnungen und kein "unsigned long long int" :P).

Ehrlich gesagt taugt mir weder die struct noch die ctypes-Lösung, vllt habt ihr auch recht und es ist sinnlos.

@0x1cedd1ce, auch im Forum? ;). Ich dachte es würde einiges Vereinfachen, wenn ich schon auf "Pythoseite" auf Größe teste.
the more they change the more they stay the same
0x1cedd1ce
User
Beiträge: 31
Registriert: Sonntag 3. Oktober 2010, 12:21

Ich meinte auch das du auf Pythonseite testest ob die Zahl im Wertebereich liegt. Das geht mit ctypes.
Nutz doch bit_length() um die Bitanzahl zu bekommen. Oder to_bytes()

Code: Alles auswählen

>>> z = 65536
>>> z.bit_length()
17
>>> z = 65535
>>> z.bit_length()
16
>>> z.to_bytes(3, 'big', signed=True)
b'\x00\xff\xff'
>>> z.to_bytes(2, 'big', signed=False)
b'\xff\xff'
BlackJack

@0x1cedd1ce:

Code: Alles auswählen

In [202]: z = 65536

In [203]: z.bit_length()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

/home/bj/<ipython console> in <module>()

AttributeError: 'int' object has no attribute 'bit_length'
Geht erst ab Python 3.x
Antworten