Seite 2 von 5
Verfasst: Samstag 23. Mai 2009, 16:11
von numerix
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
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.
Verfasst: Samstag 23. Mai 2009, 18:09
von spongebob.squarepants
@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!
Verfasst: Samstag 23. Mai 2009, 18:37
von 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.
Verfasst: Samstag 23. Mai 2009, 19:04
von Dill
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.
Verfasst: Samstag 23. Mai 2009, 19:09
von spongebob.squarepants
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
Verfasst: Samstag 23. Mai 2009, 19:10
von numerix
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).
Verfasst: Samstag 23. Mai 2009, 19:15
von spongebob.squarepants
@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...
Verfasst: Samstag 23. Mai 2009, 19:16
von spongebob.squarepants
@Numerix: Yammi. Das ist doch mal ein Anfang. Probier's gleich mal aus...
Grüsse
Verfasst: Samstag 23. Mai 2009, 19:18
von spongebob.squarepants
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
Verfasst: Samstag 23. Mai 2009, 19:31
von numerix
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:
Edit: s.strip(arg) gibt es seit Python 2.2.2
Verfasst: Samstag 23. Mai 2009, 19:50
von spongebob.squarepants
Ich habe hier 2.5.4 lokal zum Testen, kann es sein, dass es das da auch nicht gab?
Grüsse
Verfasst: Samstag 23. Mai 2009, 19:53
von spongebob.squarepants
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
Verfasst: Samstag 23. Mai 2009, 19:57
von numerix
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

Dein Python ist nicht in der Lage, mit (beliebig) großen Ganzzahlen zu rechnen. Dürfte es eigentlich gar nicht geben.
Verfasst: Samstag 23. Mai 2009, 19:59
von spongebob.squarepants
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
Verfasst: Samstag 23. Mai 2009, 20:00
von spongebob.squarepants
.... 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
Verfasst: Samstag 23. Mai 2009, 20:06
von spongebob.squarepants
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)]
Verfasst: Samstag 23. Mai 2009, 20:46
von spongebob.squarepants
Tja, und irgendwann sprach er nur noch zu sich selber...
Verfasst: Samstag 23. Mai 2009, 20:55
von numerix
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
Verfasst: Samstag 23. Mai 2009, 22:03
von spongebob.squarepants
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
Verfasst: Samstag 23. Mai 2009, 22:44
von numerix
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?