Frage zum Speichern in einer Datei

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
MrPsycho
User
Beiträge: 3
Registriert: Mittwoch 26. November 2008, 08:40

Guten Tag zusammen,
ich hoffe ich schreibe hier im richtigen Teil des Forums wenn nciht bitte ich um Nachsicht.
Ich habe eine Frage zur Speicherung einer Variable in einer Datei. Meine Aufgabe ist es eine sehr sehr lange Dezimalzahl (mehr als 30 Nachkommastellen) die mit dem Modul "decimal" erstellt wurde in eine Datei zu speichern.
Im Allg ist das kein problem. Ich rufe einfach die Datei auf und schreibe die Variable mit "write" dort hinein. Das Problem ist das er dann die Zahl ja nimmt und als Zeichenkette speichert. Die Funktion "write" verlangt ja nach einem String.
Ich möchte allerdings die Zahl direkt als ganzes speichern und nicht Zeichen für Zeichen. Es geht um ein Kodierungstool und da ist Platz gefragt.
Gibt es da eine Möglichkeit? Der Dateityp ist egal es muss auch niemand direkt auslesen das öffnen übernimmt ein anderes Programm.
In der Datei soll sich auch nur die Zahl befinden.
Ich hoffe man versteht was ich möchte wenn nicht fragt nach ich erklärs gern nochmal.:wink:
Hat jmd eine Idee?
Danke schonmal fürs durchlesen.
MfG MrPsycho
tordmor
User
Beiträge: 100
Registriert: Donnerstag 20. November 2008, 10:29
Wohnort: Stuttgart

Code: Alles auswählen

def int2bin(i):
    l = []
    while i > 0:
        i, m = divmod(i, 256)
        l.append(chr(m))
    return "".join(l)
Funktioniert aber so noch nicht bei negativen Zahlen.
The Spirit
User
Beiträge: 276
Registriert: Freitag 8. Juni 2007, 08:50
Wohnort: 84xxx Bereich
Kontaktdaten:

warum schreibst du die dezimalzahl nicht auf einmal in das file, sonder zeichen für zeichen?
liegt die zahl in deinem programm nur zeichen für zeichen vor oder verstehe ich da was falsch?
tordmor
User
Beiträge: 100
Registriert: Donnerstag 20. November 2008, 10:29
Wohnort: Stuttgart

The Spirit hat geschrieben:warum schreibst du die dezimalzahl nicht auf einmal in das file, sonder zeichen für zeichen?
liegt die zahl in deinem programm nur zeichen für zeichen vor oder verstehe ich da was falsch?
file.write(int) wandelt die Zahl in einen String um. In der Datei steht dann "12345 ..." Er möchte aber in der Datei eine binärcodierte Zahl um Platz zu sparen.
MrPsycho
User
Beiträge: 3
Registriert: Mittwoch 26. November 2008, 08:40

tordmor hat geschrieben:

Code: Alles auswählen

def int2bin(i):
    l = []
    while i > 0:
        i, m = divmod(i, 256)
        l.append(chr(m))
    return "".join(l)
Funktioniert aber so noch nicht bei negativen Zahlen.
Probiere ich dann gleich mal. Negativ wird die Zahl nicht daher fällt das weg danke dir.
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

Moment ... verstehe ich das richtig? Die Binärdarstellung einer Zahl in einer Datei (also letztlich auch ein String) soll weniger Platz verbrauchen als die Dezimaldarstellung?

Wenn das so sein sollte, bin ich entweder zu müde um es zu begreifen oder ich sollte dringend die Branche wechseln :shock:
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Pekh hat geschrieben:Moment ... verstehe ich das richtig? Die Binärdarstellung einer Zahl in einer Datei (also letztlich auch ein String) soll weniger Platz verbrauchen als die Dezimaldarstellung?
Dezimal(als String) ist jede Ziffer ein Byte.

Code: Alles auswählen

In [22]: len(int2bin(10000)), len("10000")

Out[22]: (2, 5)
MrPsycho
User
Beiträge: 3
Registriert: Mittwoch 26. November 2008, 08:40

Ganz einfaches Beispiel:
Die Zahl 134 als String wird gespeichert mit
"1"(ASCII-Nummer 49)
"3"(ASCII-Nummer 51)
"4"(ASCII-Nummer 52)
000110001 000110011 000110100
Also 3 Bytes.
Die Zahl 134 gespeichert als Integer:
10000110
Also 1 Byte.
Der Unterschied sieht atm so aus:
Orginaldatei mit Text: 45 Byte
Datei wo die Zahl als String gespeichert wurde: 55 Byte
Datei wo die Zahl als Zahl gespeichert wurde: 22 Byte

Soviel dazu.
Dann aber noch eine Frage: Die Funktion int2bin wandelt ja eine Integerzahl um. Ich habe wie gesagt eine Zahl im Datentyp Decimal mit atm 53 Nachkommastellen. Wenn ich sie so auf die Funktion loslasse kommt nur null zurück weil es die Zahl 0... ist. Das ist logisch. Ich habe jetzt einfach:

Code: Alles auswählen

e=str(iugrenze)
f=e[2:]
d=Decimal(f)
datei2=file("D:\ziel1","w")
datei2.write(int2bin(d))
Genutzt um die Zahl erst zu einem String umzuwandeln dann das 0. abzuschneiden und dann das ganze wieder zurückzuwandeln. Gibt es da vlt eine schönere/bessere Lösung?
Und wie würde das ganze dann als Rückwandlung aussehen? Ich kann zwar die Datei jetzt komplett auslesen es kommt aber nur das
"\xba\xea\x04\xb3\xa9|\xb4\x85m\xae\xea\x93W\xfbM\xffk\xf4\xd0\x8aXb"
bei raus.
Vielen Dank auch schonmal für die ganzen Antworten.
MfG MrPsycho[/code]
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Ich kenne die Größen der C-Datentypen nicht aus dem Eff-Eff, aber das `struct`-Modul könnte das Richtige sein.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Y0Gi hat geschrieben:Ich kenne die Größen der C-Datentypen nicht aus dem Eff-Eff
Nun, die exakten Größen sind ja auch von der entsprechenden Platform abhängig. Integer sind auf meinem amd64-System größer als Integer auf i386-Systemen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

MrPsycho hat geschrieben:Ich habe jetzt einfach:

Code: Alles auswählen

e=str(iugrenze)
f=e[2:]
d=Decimal(f)
datei2=file("D:\ziel1","w")
datei2.write(int2bin(d))
Genutzt um die Zahl erst zu einem String umzuwandeln dann das 0. abzuschneiden und dann das ganze wieder zurückzuwandeln. Gibt es da vlt eine schönere/bessere Lösung?
Naja, eine erhebliche Steigerung der Ästhetik ist es nicht gerade, aber du könntest es auch so machen:

Code: Alles auswählen

d = int(iugrenze*10**-iugrenze.as_tuple()[2])
tordmor
User
Beiträge: 100
Registriert: Donnerstag 20. November 2008, 10:29
Wohnort: Stuttgart

Ich war wohl geistig nicht voll da, als ich das geschrieben hab. :oops:
Zuletzt geändert von tordmor am Mittwoch 26. November 2008, 19:20, insgesamt 1-mal geändert.
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

@tordmor: Deine Version von bin2int versagt schon bei 1000.

MrPsycho: Du musst deine Daten entsprechen codieren, das ist bei Decimal zum Glück relativ unkompliziert.

Code: Alles auswählen

import decimal

def int2bin(i):
    l = []
    while i > 0:
        i, m = divmod(i, 256)
        l.append(chr(m))
    return "".join(l)

def bin2int(string):
    i = 0;
    for pos, char in enumerate(string):
        i += ord(char)*(256**pos)
    return i

def dec2bin(dec):
    #Format:
    # sign:len(digits_bin_string):digits_bin_string:exponent:
    sign, digits, exponent = dec.as_tuple()
    digits_bin_string = int2bin(int("".join(map(str, digits))))
    return ":".join((
        str(sign),
        str(len(digits_bin_string)),
        digits_bin_string,
        str(exponent), ''
    ))
def bin2dec(bin):
    def next(seek = None):
        pos = seek or bin.find(":")
        return bin[:pos], bin[pos+1:]
    while bin:
        sign, bin = next(); sign = int(sign)
        data_length, bin = next(); data_length = int(data_length)
        data, bin = next(data_length); data = str(bin2int(data))
        exponent, bin = next(); exponent = int(exponent)
        yield decimal.Decimal(("-" if sign else "") + data[:exponent] + "." + data[exponent:])

print list(bin2dec(dec2bin(decimal.Decimal("-3.14156"))+dec2bin(decimal.Decimal("3.14156"))))
bin2dec ist leider etwas unübersichtlich geworden, da es nonlocal leider noch nicht gibt(kann man sicherlich auch eleganter lösen...).
Antworten