Float in Int abbilden

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.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

spongebob.squarepants hat geschrieben:@numerix: Das Heron Verfahren (ist das die babylonische Wurzel?) konvergiert gut, tendiert aber bei Verwendung des Rational Datentyps (siehe mein letztes Posting), den ich ganz schick finde, selbst bei Verwendung von longs schnell zu Long Overflows, vornehmlich bei dem additiven Part (schon getestet). Aber wenn Du da andere Erfahrungen hast, würde es mich freuen, davon zu hören.
Long Overflow :shock:
Das ist dann aber ein Problem dieses Rational-Moduls und kein eigentliches Python-Problem. Ab einer bestimmten Anzahl von Nachkommastellen (ich rede hier von einigen zigtausend) dauert die Berechnung nur einfach zu lange. Begrenzt ist die Genauigkeit nur durch den Hauptspeicher und die Zeit, die du warten willst, bis das Ergebnis kommt ... :)

Und was meinst du mit "additivem Teil"?
Die Idee des Heron-Verfahrens ist die: Man fasst den Radikand als Maßzahl der Fläche eines Quadrats auf und versucht, die Seitenlängen dieses Quadrats zu berechnen - das wäre dann das gewünschte Ergebnis.
Dazu setzt man ein Rechteck mit dem gleichen Flächeninhalt an und approximiert in jedem Schritt die Seiten ein Stück mehr in Richtung Quadrat, indem man in jedem Schritt den Mittelwert der beiden Seiten nimmt (ergibt eine der beiden neuen Seiten) und den Flächeninhalt durch diesen Mittelwert dividiert (ergibt die andere Seite).

Nachtrag: Ein Blick auf bzw. in das Rational-Modul klärt die Sache: Um die float-Repräsentation eines Bruchs a/b darzustellen, wird float(a)/float(b) berechnet. Daraus erklärt sich dann auch der Overflow, denn man kann eben nicht beliebig große ints/longs in floats umwandeln.
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

@Dill: Ich habe "die Community" dort noch gar nicht gesucht, weil ich hier ein Python Problem sehe. Aber das hatte ich wohl auch schon erwähnt. Ansonsten entscheidet für mich immer, ob der Funktionsumfang des Chips den Anforderungen genügt. Die Sprache ist dann eher zweitrangig. Dieser Chip unterstützt GSM, GPS, WiFi Positionierungen. I.d.R. braucht kein Mensch dafür float oder decimal Support. Lediglich eine spezielle Vorfilterung erfordert diese Rechnereien.

Long Overflow: Ich denke, diese Fehlermeldung ist ziemlich eindeutig:
OverflowError: long int too long to convert. Und sicher - es ist ein Problem des Rational-Moduls, wie man sehen kann, da es nicht mehr als long precision macht in der derzeitigen Realisierung.

Additiver Teil: Ich meinte das hier: http://de.wikipedia.org/wiki/Heron-Verfahren. Die Addition der beiden Rationals erzeugt einen zu grossen Hauptnenner für long .

Die float Repräsentation verwende ich aus naheliegenden Gründen nicht. Ich nutze "print" zur Ausgabe der Ergebnisse. Dort und eben (s.o.) beim HN gibt's den o.g. Overflow.

Grüsse - und bitte keine Diskussion mehr über den Chip. Da bin ich an den AG gebunden. Wer eine Idee hat, wie man mit longs den Pythagoras zwischen zwei floats mit 2-3 Vorkomma und 6 Nachkommastellen machen kann - Willkommen!
BlackJack

@spongebob.squarepants: Das ist aber kein Overflow in Python's `long`\s, sondern ein Problem mit einer Funktion die gerne ein `int` haben möchte.
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

spongebob, das sind keine "chips" sondern komplette module, sag das doch, dann muss ich mich nicht erregen. warum rufst du nicht einfach bei telit an, die haben sicher eine fertige lösung für dein problem.
http://www.kinderpornos.info
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

OK. Welche könnte das sein? Ich habe den Konstruktor von Rational so geändert, dass
self.n = long(a / g)
self.d = long(b / g)

weil mit int ging vorher nicht allzuviel bei der von mir gebrauchten Präzision. Kann ja dann nur ein Print sein, denn die exception zeigt auf diese Stelle
def __str__ ( self ):
'''Display self as a string.
'''
return "%ld/%ld" % ( self.n, self.d )

Hier ein Beispiel:

from rational import *
print Rational(50123456, 1000000) * Rational(151123, 1000000)

Traceback (innermost last):
File "G:\test\t.py", line 2, in ?
print Rational(50123456, 1000000) * Rational(151123, 1000000)
File "G:\test\rational.py", line 84, in __str__
return "%ld/%ld" % ( self.n, self.d )
OverflowError: long int too long to convert

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

spongebob.squarepants hat geschrieben:Wer eine Idee hat, wie man mit longs den Pythagoras zwischen zwei floats mit 2-3 Vorkomma und 6 Nachkommastellen machen kann - Willkommen!
Das ist doch keine große Sache.
Ich mache mal einen Anfang. Was noch fehlt, steht im Quelltext.

Code: Alles auswählen

# -*- coding: iso-8859-15 -*-

def bruch(x):
    """x ist eine Zeichenkette in float-Darstellung.
    Liefert einen gekürzten Bruch z/n als Tupel (z,n)."""
    ganz, nkst = x.rstrip("0").split(".")
    nenner = 10**len(nkst)
    zaehler = int(ganz) * nenner + int(nkst)
    # hier evtl. kürzen
    return zaehler, nenner

def hypotenuse(x, y):
    """x, y sind Zeichenketten mit einer float-Darstellung.
    Liefert das Quadrat der Hypotenuse für die Katheten x und y
    als Bruch (z,n)."""
    (az, an), (bz, bn) = bruch(x), bruch(y)
    cz, cn = az*az*bn*bn+an*an*bz*bz, an*an*bn*bn
    # hier sollte man kürzen: Euklid
    # dann die Quadratwurzel berechnen: Heron
    # und danach ohne Verwendung von float() in eine float-Repräsentation umwandeln
    return cz, cn

a = "6.5004"
b = "2.561"
z, n = hypotenuse(a, b)

# Zur Kontrolle
print float(z)/float(n)
print float(a)**2 + float(b)**2
Schicker wird es natürlich, wenn du einen Klassenentwurf machst und Brüche nicht als Tupel darstellst. Nach meiner Erfahrung leidet darunter allerdings die Performance (falls es darauf ankommt).
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

@Dill: Nun wollen wir mal nicht kleinlicher sein, als der Papst. Ich hatte die angemailt - keine Antwort.

Ich versuche, ohne dass ich derzeit ein derartiges Modul habe, die "Firmware" vorab auf meinem Nokia (PyS60) zu bauen. Also - wer das nicht schick und interessant findet, hat noch nie für einen 8051 Clone Firmware gebastelt...
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

@Numerix: Yammi. Das ist doch mal ein Anfang. Probier's gleich mal aus...
Grüsse
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Huch? Wass'n hier los?

Traceback (innermost last):
File "G:\test\t1.py", line 25, in ?
z, n = hypotenuse(a, b)
File "G:\test\t1.py", line 16, in hypotenuse
(az, an), (bz, bn) = bruch(x), bruch(y)
File "G:\test\t1.py", line 6, in bruch
ganz, nkst = x.rstrip("0").split(".")
TypeError: strip requires exactly 0 arguments; 1 given
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

spongebob.squarepants hat geschrieben:Huch? Wass'n hier los?

Traceback (innermost last):
File "G:\test\t1.py", line 25, in ?
z, n = hypotenuse(a, b)
File "G:\test\t1.py", line 16, in hypotenuse
(az, an), (bz, bn) = bruch(x), bruch(y)
File "G:\test\t1.py", line 6, in bruch
ganz, nkst = x.rstrip("0").split(".")
TypeError: strip requires exactly 0 arguments; 1 given
Ah, strip() mit Parameter scheint es in Python 1.5 noch nicht gegeben zu haben. Ist kein Problem, kann man auch weglassen. Also einfach:

Code: Alles auswählen

ganz, nkst = x.split(".")
Edit: s.strip(arg) gibt es seit Python 2.2.2
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Ich habe hier 2.5.4 lokal zum Testen, kann es sein, dass es das da auch nicht gab?

Grüsse
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Nu krachts woanders:
Traceback (innermost last):
File "G:\test\t1.py", line 25, in ?
z, n = hypotenuse(a, b)
File "G:\test\t1.py", line 17, in hypotenuse
cz, cn = az*az*bn*bn+an*an*bz*bz, an*an*bn*bn
OverflowError: integer multiplication
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

spongebob.squarepants hat geschrieben:Nu krachts woanders:
Traceback (innermost last):
File "G:\test\t1.py", line 25, in ?
z, n = hypotenuse(a, b)
File "G:\test\t1.py", line 17, in hypotenuse
cz, cn = az*az*bn*bn+an*an*bz*bz, an*an*bn*bn
OverflowError: integer multiplication
:shock: Dein Python ist nicht in der Lage, mit (beliebig) großen Ganzzahlen zu rechnen. Dürfte es eigentlich gar nicht geben.
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Ich korrigiere: Ein print sys.version brachte etwas ans Licht, was ich schon vermutet hatte: Ich habe zwar 2.5.4 auf dem PC und die erscheint auch, wenn ich auf der Console "python" eingebe, aber die _nachträgliche_ Installation des Telit EasyScript Paketes hat die Verknüpfung von "*.py" Dateien auf die von denen installierte 1.5.2 umgebogen...

Argghghg
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

.... deswegen wohl auch die Missverständnisse mit dem Overflow...

Nun, Py 1.5.2 zeigt es: Es _gab_ mal eine Python-Variante, die das nicht konnte :)

Und wieder die Frage: Gibt's da was von Ratiopharm? Entschuldigung, wenn ich so nerve und vielen Dank für Deine/Eure Patience.

Grüsse
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Das Seltsame: Die 1.5.2 Quick Reference spricht davon:

Floats, integers and long integers.
Floats are implemented with C doubles.
Integers are implemented with C longs.
Long integers have unlimited size (only limit is system resources)

Also haben die sich bei Telit offenbar eine eigene 1.5.2 gebastelt. Der sys.version string bringt


1.5.2+ (#0, Oct 1 2004, 15:39:52) [MSC 32 bit (Intel)]
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Tja, und irgendwann sprach er nur noch zu sich selber...
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Probier das doch mal (Funktion bruch(x) durch die folgende ersetzen, den Rest so lassen):

Code: Alles auswählen

def bruch(x):
    """x ist eine Zeichenkette in float-Darstellung.
    Liefert einen gekürzten Bruch z/n als Tupel (z,n)."""
    ganz, nkst = x.split(".")
    nenner = long(10**len(nkst))
    zaehler = long(ganz) * nenner + long(nkst)
    return zaehler, nenner
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Danke, numerix. Das habe ich inzwischen selbst rausgefunden. Habe als Tupel nur dies zurückgegeben:
return long(zaehler), long(nenner)

Trotzdem bin ich jetzt etwas durcheinander: Mit folgenden Werten ergibt "print z,n" dies

a = "65.125004"
b = "2.561"
z, n = hypotenuse(a, b)
print z, n


G:\test>t1.py
4247824867000016000000 1000000000000000000

Ich staune über diese unglaublich grossen ganzen Zahlen... Unglücklicherweise behauptet die Beschreibung zum Telit Python, dass "long nicht unterstützt" ist. Vermutlich wird long bei denen nur unsigned 32 bit int sein...:(

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

spongebob.squarepants hat geschrieben: G:\test>t1.py
4247824867000016000000 1000000000000000000

Ich staune über diese unglaublich grossen ganzen Zahlen...
Wenn du den euklidischen Algorithmus vorschaltest, wird daraus:
1220348029 25000000

Edit: Das Ergebnis ist jetzt aber nicht mit Python 1.5 produziert, richtig?
Antworten