Gleitkommazahlen paarweise speichern

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.
musikus
User
Beiträge: 14
Registriert: Donnerstag 9. Oktober 2008, 13:39
Kontaktdaten:

Gleitkommazahlen paarweise speichern

Beitragvon musikus » Donnerstag 9. Oktober 2008, 17:06

Hallo Python Freunde, bin neu hier und habe ein größeres Problem.
Um in Python einzusteigen, habe ich mir ein uraltes Turbo Pascal Programm
vorgenommen.

Im Prinzip war es auch nicht sehr schwer das Programm in Python umzuschreiben
nur mit dem Speichern und Einlesen von x, y Koordinaten klemmt es. Auch nach
langem Suchen konnte ich im Internet nichts finden.

Am einfachsten wäre es wenn ich folgende mit Turbo Pascal erzeugte Daten
lesen könnte.

writelin(x_neu:6:3,' ',y_neu:5:3);
x_neu , y_neu := real; so wurden die Daten mit Pascal gespeichert.

Da mir das nicht gelungen ist habe ich versucht das Interpolationsprogramm
umzuschreiben und damit eine neue Datei zu erstellen was aber auch gescheitert ist.

Auszug aus der Ursprungsdatei, diese wurde vor vielen Jahren von Hand eingegeben.
Die Datei enthält x,y Koordinaten der Welt. Da die "Messpunkte" unterschiedliche
Abstände haben was beim Plotten unschöne Ecken ergab, wurde ein Programm
entwickelt um diese Daten zu interpolieren.

B BALEAREN (IBIZA) ========= INSELN ==========
N 38 37 O 1 11
N 38 51 O 1 22
N 38 51 O 1 46
N 38 32 O 1 34
N 38 37 O 1 11
B MALLORCA
N 39 18 O 2 33
N 39 51 O 3 32
N 39 32 O 3 32
N 39 32 O 3 49
N 39 5 O 3 32
N 39 18 O 2 33
B MENORCA
N 40 2 O 4 7
N 40 2 O 4 31
N 39 42 O 4 42
N 39 51 O 4 11
N 40 2 O 4 7

Was ich brauch ist eine Funktion mit der man reelle x,y Wertepaare (2 Gleitkommazahlen)
in eine Datei schreiben und eine Funktion mit der ich diese Werte wieder auslesen kann.
Ich hoffe das mir jemand weiterhelfen kann.

Gruß musikus

Falls nicht verboten hier noch ein Link um sich die "Welt" anzusehen
http://www.sexysax.eu/Adelaide.pdf
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Beitragvon numerix » Donnerstag 9. Oktober 2008, 18:10

Hallo musikus, willkommen im Forum!

Leider verstehe ich nicht so recht, was genau du willst.

Du könntest z.B. mal das TP-Programm posten oder deinen bisherigen Python-Quelltext und daran dann aufzeigen, was du gerne hättest, was du schon versucht hast und was nicht klappt.

"Im Internet" nach Lösungen zu suchen, ist wohl nicht der richtige Weg.
Stattdessen als Empfehlung "Das Tutorial": http://docs.python.org/tutorial/index.html

Lies dich doch da mal ein. :wink:
farid
User
Beiträge: 95
Registriert: Mittwoch 8. Oktober 2008, 15:37

Re: Gleitkommazahlen paarweise speichern

Beitragvon farid » Donnerstag 9. Oktober 2008, 19:24

musikus hat geschrieben:Was ich brauch ist eine Funktion mit der man reelle x,y Wertepaare (2 Gleitkommazahlen)
in eine Datei schreiben und eine Funktion mit der ich diese Werte wieder auslesen kann.
Ich hoffe das mir jemand weiterhelfen kann.


Meinst Du sowas?

Code: Alles auswählen

#!/usr/bin/env python
# real.py -- read and write float pairs in a text file

def read_floats(path_to_file):
    "Read and return a list of float pairs from a text file"
    result = []
    f = open(path_to_file, 'r')
    for line in f:
        num_1, num_2 = line.split()
        result.append((float(num_1), float(num_2)))
    f.close()
    return result

def write_floats(path_to_file, list_of_floats):
    "Write a list of float pairs into a text file"
    f = open(path_to_file, 'w')
    for nval_1, nval_2 in list_of_floats:
        f.write(str(nval_1) + " " + str(nval_2) + "\n")
    f.close()

def demo(path_to_file):
    "Shows how to use read_floats and write_floats"
    the_output_list = [ (1.0, 1.5), (3.0, 3.5), (47.7, 11.8) ]
    write_floats(path_to_file, the_output_list)
    print "saved: ", the_output_list

    the_input_list = read_floats(path_to_file)
    print "loaded: ", the_input_list

if __name__ == '__main__':
    demo('real.dat')


Die Ausführung ergibt:

Code: Alles auswählen

$ python real.py
saved:  [(1.0, 1.5), (3.0, 3.5), (47.700000000000003, 11.800000000000001)]
loaded:  [(1.0, 1.5), (3.0, 3.5), (47.700000000000003, 11.800000000000001)]

$ cat real.dat
1.0 1.5
3.0 3.5
47.7 11.8


Natürlich ist der Code noch nicht ganz robust, und für Newbies etwas ausführlich formuliert.

Beispielsweise könnte die Datei nicht les- oder schreibbar sein, oder in der Datei könnte sich etwas befinden, was sich nicht zu einem float konvertieren läßt. In dem Fall solltest Du entsprechende try: except-Blöcke hinzufügen, um die jeweiligen Fehler abzufangen.

Es gibt auch andere Möglichkeiten, floats in eine Datei zu speichern: z.B. direkt im Binärformat.
musikus
User
Beiträge: 14
Registriert: Donnerstag 9. Oktober 2008, 13:39
Kontaktdaten:

Beitragvon musikus » Freitag 10. Oktober 2008, 10:03

numerix hat geschrieben:Hallo musikus, willkommen im Forum!

Leider verstehe ich nicht so recht, was genau du willst.

Du könntest z.B. mal das TP-Programm posten oder deinen bisherigen Python-Quelltext und daran dann aufzeigen, was du gerne hättest, was du schon versucht hast und was nicht klappt.

"Im Internet" nach Lösungen zu suchen, ist wohl nicht der richtige Weg.
Stattdessen als Empfehlung "Das Tutorial": http://docs.python.org/tutorial/index.html

Lies dich doch da mal ein. :wink:


Hallo numerix, vielen Dank für den Tip, werde mir das mal anschauen.
Bin leider gestern erst sehr spät heimgekommen so das ich erst jetzt antworten kann.

Füge mal zwei Pascal Prozeduren bei, mit der interpolieren.pas wurde der File erzeugt den ich gern in pyhton lesen möchte und die Welt.pas ist eine Testversion um die "Welt" auf dem Bildschirm auszugeben, das Originalprogramm schreibt die Daten in einen HPGL File, daa ist auch der
Grund das es die Variable PEN gibt.

Habe die beiden Pascal Proceduren wieder entfernt da sie nicht formatiert
sind, muss erst einmal herausfinden wie das funktioniert, sorry.

Auf jeden Fall vielen Dank für die Hilfe.
Gruß musikus
[code=python][/code]
musikus
User
Beiträge: 14
Registriert: Donnerstag 9. Oktober 2008, 13:39
Kontaktdaten:

Re: Gleitkommazahlen paarweise speichern

Beitragvon musikus » Freitag 10. Oktober 2008, 10:24

farid hat geschrieben:
musikus hat geschrieben:Was ich brauch ist eine Funktion mit der man reelle x,y Wertepaare (2 Gleitkommazahlen)
in eine Datei schreiben und eine Funktion mit der ich diese Werte wieder auslesen kann.
Ich hoffe das mir jemand weiterhelfen kann.


Meinst Du sowas?

Code: Alles auswählen

#!/usr/bin/env python
# real.py -- read and write float pairs in a text file

def read_floats(path_to_file):
    "Read and return a list of float pairs from a text file"
    result = []
    f = open(path_to_file, 'r')
    for line in f:
        num_1, num_2 = line.split()
        result.append((float(num_1), float(num_2)))
    f.close()
    return result

def write_floats(path_to_file, list_of_floats):
    "Write a list of float pairs into a text file"
    f = open(path_to_file, 'w')
    for nval_1, nval_2 in list_of_floats:
        f.write(str(nval_1) + " " + str(nval_2) + "\n")
    f.close()

def demo(path_to_file):
    "Shows how to use read_floats and write_floats"
    the_output_list = [ (1.0, 1.5), (3.0, 3.5), (47.7, 11.8) ]
    write_floats(path_to_file, the_output_list)
    print "saved: ", the_output_list

    the_input_list = read_floats(path_to_file)
    print "loaded: ", the_input_list

if __name__ == '__main__':
    demo('real.dat')


Die Ausführung ergibt:

Code: Alles auswählen

$ python real.py
saved:  [(1.0, 1.5), (3.0, 3.5), (47.700000000000003, 11.800000000000001)]
loaded:  [(1.0, 1.5), (3.0, 3.5), (47.700000000000003, 11.800000000000001)]

$ cat real.dat
1.0 1.5
3.0 3.5
47.7 11.8


Natürlich ist der Code noch nicht ganz robust, und für Newbies etwas ausführlich formuliert.

Beispielsweise könnte die Datei nicht les- oder schreibbar sein, oder in der Datei könnte sich etwas befinden, was sich nicht zu einem float konvertieren läßt. In dem Fall solltest Du entsprechende try: except-Blöcke hinzufügen, um die jeweiligen Fehler abzufangen.

Es gibt auch andere Möglichkeiten, floats in eine Datei zu speichern: z.B. direkt im Binärformat.



Hallo farid, vielen Dank für die schnelle Hilfe, ich muss mir aber deinen Vorschlag erst einmal in Ruhe ansehen. Die Möglichkeit direkt im Binärformat zu speichern hört sich für mich auch gut an. Am einfachsten wäre es aber wenn ich die schon vorhandene Datei "KOOR4.INT" mit Python einlesen könnte, wollte diese Datei schon mitschicken weiß aber nicht wie das funktioniert :-(


Nochmals vielen Dank für die freundliche Hilfe

Gruß musikus


:cry:
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Re: Gleitkommazahlen paarweise speichern

Beitragvon numerix » Freitag 10. Oktober 2008, 10:49

musikus hat geschrieben:Am einfachsten wäre es aber wenn ich die schon vorhandene Datei "KOOR4.INT" mit Python einlesen könnte, wollte diese Datei schon mitschicken weiß aber nicht wie das funktioniert :-(


Da es - wenn ich es recht verstanden habe - keine Binärdatei ist, kannst du sie doch mit einem Texteditor öffnen und ein paar Zeilen daraus einfach hier posten.

Ansonsten gilt nach wie vor: Nimm dir das Tutorial vor. Nimm dir Zeit dafür und experimentiere viel im interaktiven Modus (Shell).
BlackJack

Beitragvon BlackJack » Freitag 10. Oktober 2008, 10:52

Zeig doch einfach mal den Pascal-Quelltext zum Lesen und eventuell Schreiben und einen kleinen Ausschnitt aus der `KOOR4.INT`.

Syntax-Highlighting für Pascal kann das Forum nicht, aber ein einfacher `code`-Block reicht ja auch.

Falls Du Webspace zur Verfügung hast, kannst Du die Dateien vielleicht auch als Archiv hochladen und hier den Link veröffentlichen.
musikus
User
Beiträge: 14
Registriert: Donnerstag 9. Oktober 2008, 13:39
Kontaktdaten:

Beitragvon musikus » Freitag 10. Oktober 2008, 14:22

BlackJack hat geschrieben:Zeig doch einfach mal den Pascal-Quelltext zum Lesen und eventuell Schreiben und einen kleinen Ausschnitt aus der `KOOR4.INT`.

Syntax-Highlighting für Pascal kann das Forum nicht, aber ein einfacher `code`-Block reicht ja auch.

Falls Du Webspace zur Verfügung hast, kannst Du die Dateien vielleicht auch als Archiv hochladen und hier den Link veröffentlichen.


Hallo, da sich jetzt schon drei Experten bemühen mir zu helfen was ich sehr positiv finde, will ich jetzt allen zusammen antworten.

Als Erstes habe ich ein Archiv erzeugt und 3 Dateien hochgeladen, der Link ist http://www.sexysax.eu/Archiv/

Die Datei KOOR4.INT ist eine Binärdatei sonst hätte ich auch kein Problem, sie wurde mit der Pascal Procedure interpolieren.pas aus
einem Textfile erstellt.

Die Procedure Welt.pas ist eine Testversion mit Bildschirmausgabe, die originale Procedur speichert die Daten als HPGL Plottfile ab.
Mit dieser Procedure müssen die x,y Koordinaten aus der Datei KOOR4.INT eingelesen, verarbeitet und je nach dem auf dem Bildschirm
ausgegeben oder als HPGL File gespeichert werden. Das einzige Problem bis jetzt ist das ich den schon vorhandenen File KOOR4.INT nicht lesen kann.

Gruß musikus
farid
User
Beiträge: 95
Registriert: Mittwoch 8. Oktober 2008, 15:37

Binärformat

Beitragvon farid » Freitag 10. Oktober 2008, 15:02

musikus hat geschrieben:Die Datei KOOR4.INT ist eine Binärdatei sonst hätte ich auch kein Problem, sie wurde mit der Pascal Procedure interpolieren.pas aus einem Textfile erstellt.


Hi musikus,

ich hab' noch nicht genau reingeschaut, aber generell: falls Pascal die Binärdaten als Standard IEEE-754 Floats oder Doubles speichert, dann kann man sie wieder einlesen mit Hilfe der Funktion array.fromfile (oder sie schreiben mit der Funktion array.tofile).

http://docs.python.org/library/array.html

Aber wenn ich mich dunkel erinnere, benutzte Turbo Pascal ein eigenes Real-Format mit 6 Bytes pro Real (?):

http://www.macdonald.egate.net/CompSci/ ... types.html

In dem Fall müsste man erst googlen. Vielleicht hat jemand schon ein Python-Modul geschrieben, um dieses Format zu entziffern...
BlackJack

Beitragvon BlackJack » Freitag 10. Oktober 2008, 15:29

@farid: Das mit den 6-Byte-`Real`\s überrascht mich. Kann es sein, dass die Quelle sich da irrt? Wenn man sich die Datei im Hexeditor anschaut, würde ich auf den ersten Blick behaupten ein 4-Byte-Muster zu sehen.

Notfalls würde ich an musikus' Stelle ein kleines Pascal-Programm schreiben, dass die Binärdatei in eine Textdatei umwandelt.

@musikus: Die Datei ist aber nicht mit dem `WriteLn()` aus Deinem ersten Beitrag entstanden. Das hätte nämlich eine Textdatei erstellt. In der `Interpolieren.pas` wird die `KOOR4.INT` zwar geöffnet und am Ende geschlossen, es gibt aber keinen einzigen Schreibbefehl in diese Datei!?

Na egal, wenn es sich um 4-Byte-`float`\s handelt, die C auf dem Rechner verstehen würde, kann man das ganze, wie farid schon sagte, mit dem `array`-Modul einlesen:

Code: Alles auswählen

#!/usr/bin/env python
from __future__ import with_statement
from array import array
from pprint import pprint


def read_coordinates(filename):
    with open(filename) as coordinate_file:
        flat_coordinates = array('f')
        flat_coordinates.fromstring(coordinate_file.read())
        return zip(flat_coordinates, flat_coordinates)


def main():
    coordinates = read_coordinates('KOOR4.INT')
    pprint(coordinates)


if __name__ == '__main__' :
    main()
musikus
User
Beiträge: 14
Registriert: Donnerstag 9. Oktober 2008, 13:39
Kontaktdaten:

Beitragvon musikus » Freitag 10. Oktober 2008, 16:48

BlackJack hat geschrieben:@farid: Das mit den 6-Byte-`Real`\s überrascht mich. Kann es sein, dass die Quelle sich da irrt? Wenn man sich die Datei im Hexeditor anschaut, würde ich auf den ersten Blick behaupten ein 4-Byte-Muster zu sehen.

Notfalls würde ich an musikus' Stelle ein kleines Pascal-Programm schreiben, dass die Binärdatei in eine Textdatei umwandelt.

@musikus: Die Datei ist aber nicht mit dem `WriteLn()` aus Deinem ersten Beitrag entstanden. Das hätte nämlich eine Textdatei erstellt. In der `Interpolieren.pas` wird die `KOOR4.INT` zwar geöffnet und am Ende geschlossen, es gibt aber keinen einzigen Schreibbefehl in diese Datei!?

Na egal, wenn es sich um 4-Byte-`float`\s handelt, die C auf dem Rechner verstehen würde, kann man das ganze, wie farid schon sagte, mit dem `array`-Modul einlesen:

Code: Alles auswählen

#!/usr/bin/env python
from __future__ import with_statement
from array import array
from pprint import pprint


def read_coordinates(filename):
    with open(filename) as coordinate_file:
        flat_coordinates = array('f')
        flat_coordinates.fromstring(coordinate_file.read())
        return zip(flat_coordinates, flat_coordinates)


def main():
    coordinates = read_coordinates('KOOR4.INT')
    pprint(coordinates)


if __name__ == '__main__' :
    main()



Hi BlackJack, in der Tat die KOOR4.INT wurde nicht mit der Procedure interpolieren.pas erzeugt die ich hochgeladen hatte, bitte um Entschuldigung.

Es ist nicht nur schon 20 Jahre her seit ich das Programm erstellt habe, es gibt auch noch mehrere Versionen. Um sicher zu gehen, habe ich die vermutlich beste Version von interpolieren.pas gesucht und habe damit die Datei KOOR4.INT neu erstellt, beide Files habe ich auf meinem Server ersetzt.
Leider hatte ich noch keine Zeit die vielen Vorschläge zu testen, werde mich wieder melden wenn ich das getan habe.

Hier noch einmal der Link mit den entsprechenden Files
http://www.sexysax.eu/Archiv/

Gruß musikus
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Beitragvon numerix » Freitag 10. Oktober 2008, 18:01

@BlackJack: Der Datentyp real von Turbo Pascal umfasst definitiv 6 Byte. Bei Verwendung des numerischen Coprozessors (falls vorhanden, sonst emuliert :D ), gibt es noch die Fließkommadatentypen single (4 Byte), double (8 Byte) und extended (10 Byte).

@musikus: Deine Prozedur interpolieren.pas verwendet eine Datei Namens KOOR4.DAT, bei der es sich allem Anschein nach um eine Datei vom Typ text handelt. Leider fehlen die Variablendeklarationen - das wäre hilfreich, wenn man die hätte.

Am einfachsten wäre es doch, wenn du mal einen Ausschnitt aus DIESER Datei zeigst.
musikus
User
Beiträge: 14
Registriert: Donnerstag 9. Oktober 2008, 13:39
Kontaktdaten:

Beitragvon musikus » Freitag 10. Oktober 2008, 18:44

numerix hat geschrieben:@BlackJack: Der Datentyp real von Turbo Pascal umfasst definitiv 6 Byte. Bei Verwendung des numerischen Coprozessors (falls vorhanden, sonst emuliert :D ), gibt es noch die Fließkommadatentypen single (4 Byte), double (8 Byte) und extended (10 Byte).

@musikus: Deine Prozedur interpolieren.pas verwendet eine Datei Namens KOOR4.DAT, bei der es sich allem Anschein nach um eine Datei vom Typ text handelt. Leider fehlen die Variablendeklarationen - das wäre hilfreich, wenn man die hätte.

Am einfachsten wäre es doch, wenn du mal einen Ausschnitt aus DIESER Datei zeigst.


Hi BlackJack, die Datei KOOR4.INT wird von der Procedure interpolieren.pas aus einem Textfile erstellt ist aber kein Textfile. KOOR4.INT habe ich im "Archiv" auf meinem Server hinterlegt, der Datentyp ist Single. Teste gerade die verschiedenen Vorschläge, hatte aber noch keinen Erfolg.

Link: http://www.sexysax.eu/Archiv/

Gruß musikus
BlackJack

Beitragvon BlackJack » Freitag 10. Oktober 2008, 19:06

@musikus: Wenn man die Datei als 4-Byte-C-Floats einliest, endet sie mit den 200.0-Werten, wie sie `Interpolieren.pas` als Endkennzeichen verwendet. Mein Vorschlag sollte also eigentlich funktionieren.

Nachtrag: Ups. Ich habe einen Fehler gemacht. Hier die Korrektur:

Code: Alles auswählen

def read_coordinates(filename):
    with open(filename) as coordinate_file:
        flat_coordinates = array('f')
        flat_coordinates.fromstring(coordinate_file.read())
        tmp = iter(flat_coordinates)
        return zip(tmp, tmp)
musikus
User
Beiträge: 14
Registriert: Donnerstag 9. Oktober 2008, 13:39
Kontaktdaten:

Beitragvon musikus » Freitag 10. Oktober 2008, 20:36

BlackJack hat geschrieben:@musikus: Wenn man die Datei als 4-Byte-C-Floats einliest, endet sie mit den 200.0-Werten, wie sie `Interpolieren.pas` als Endkennzeichen verwendet. Mein Vorschlag sollte also eigentlich funktionieren.

Nachtrag: Ups. Ich habe einen Fehler gemacht. Hier die Korrektur:

Code: Alles auswählen

def read_coordinates(filename):
    with open(filename) as coordinate_file:
        flat_coordinates = array('f')
        flat_coordinates.fromstring(coordinate_file.read())
        tmp = iter(flat_coordinates)
        return zip(tmp, tmp)


Hi BlackJack, auch nachdem ich den Fehler behoben habe funktioniert das Einlesen nicht, folgende Fehlermeldung kommt:


Traceback (most recent call last):
File "C:\py_source\interpol\lese.py", line 20, in <module>
main()
File "C:\py_source\interpol\lese.py", line 15, in main
coordinates = read_coordinates('KOOR4.INT')
File "C:\py_source\interpol\lese.py", line 9, in read_coordinates
flat_coordinates.fromstring(coordinate_file.read())
ValueError: string length not a multiple of item size

Da blutiger Anfänger kann ich mit der Fehlermeldung nicht viel anfangen, was mir auffällt ist das der Fehler mit einer Stringlänge zusammenhängt.

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot]