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.
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?
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Ja, olle Euklid funktioniert hier auch recht fein.

Das Blöde: sysinfo.version sagt 1.5.2... Irgendwie glaube ich, dass die auf meinem PC laufende 1.5.2 nicht identisch sein wird mit dem, was auf dem Chip läuft... :(

Vielen Dank für Deine Hilfe, wie auch immer.
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Darf ich noch mal um einen kleinen Tipp bitten?

Habe das Ganze mal in eine Klasse gepackt.

Code: Alles auswählen

class numerix:
	def __init__(self, floatstr):
		intpart, fraction = floatstr.split(".") 
		self.d = long(10**len(fraction)) 
		self.n = long(intpart) * self.d + long(fraction) 
		self.n, self.d = self.reduce()
....
reduce ist der Kürzungsalg. Was ich gerne erreichen würde, ist die sofortige Zuweisung eines Tupels bei

huhu = numerix("1.2345")

Im obigen Fall enthält huhu ja nicht das Tupel, sondern wohl das numerix Object. Irgendwie reicht mein Python dafür noch nicht aus...

Grüsse
BlackJack

Das geht nicht, wäre aber auch schlechter Stil. Wenn man eine Klasse aufruft erwartet jeder dass da auch ein Exemplar dieser Klasse heraus kommt.

Von `numerix.reduce()` würde ich das übrigens auch erwarten. Entweder dass, oder das die Methode das `numerix`-Objekt schon selbst verändert.

Nach den üblichen Namenskonventionen müsste die Klasse übrigens `Numrix` heissen.

Da Python 1.5 wirklich sehr alt ist, bin ich jetzt mal vorsichtig mit Vorschlägen. Bei einem aktuellen Python hätte man `__iter__()` implementieren können und dann ``a, b = Numerix('1.2345')`` schreiben können.
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Danke für die Tipps. Ja, self.reduce macht bereits die Manipulationen, das hatte ich übersehen. Insofern war die nochmalige Zuweisung Overkill. Ist raus. Ich habe mir jetzt mit einer Methode "get" geholfen, komme aber auch noch nicht weiter.

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

spongebob.squarepants hat geschrieben:Ich habe mir jetzt mit einer Methode "get" geholfen, komme aber auch noch nicht weiter.
Was ist denn der letzte Stand? Was klappt und was noch nicht?
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Moin Numerix,

OK, hier ist der letzte Stand, obwohl es so spät war, dass da irgendwas vermurkst ist. Zumindest klappte mit dieser Klasse der Heron überhaupt nicht.

Code: Alles auswählen

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

def euclidian(a, b):
    if  b == 0:
		return a
    else:
        return euclidian(b, a % b)

class Numerix:
	def __init__(self, floatstr):
		intpart, fraction = floatstr.split(".") 
		self.d = long(10**len(fraction)) 
		self.n = long(intpart) * self.d + long(fraction) 
		self.reduce()
		
	def reduce(self):
		gcd = euclidian(self.n, self.d)
		if gcd != 0:
			self.n = self.n / gcd 
			self.d = self.d / gcd

	def __add__(self, o):
		self.n = self.n * o.d + o.n * self.d
		self.d = self.d * o.d
		self.reduce()
		return self.clone()
 	
 	def __sub__(self, o):
		self.n = self.n * o.d - o.n * self.d
		self.d = self.d * o.d
		self.reduce()
		return self.clone()
				
	def __mul__(self, o):
		self.n, self.d = self.n * o.n, self.d * o.d 
		self.reduce()
		return self.clone()

	def __div__(self, o):
		self.n, self.d = self.n * o.d, self.d * o.n 
		self.reduce()
		return self.clone()
	
	def __str__(self):
		return "%ld/%ld" % (self.n, self.d)
							
	def get(self):
		return self.n, self.d

	def clone(self):
		no = Numerix("0.0")
		no.n = self.n
		no.d = self.d
		return no

Dies ist die Klasse. Damit klappt sowas, wie:

a = "65.125004"
b = "2.561"

na = Numerix(a)
nb = Numerix(b)

nc = na*nb
print nc.n, nc.d, float(nc.n)/float(nc.d)

"41696283811 250000000 166.785135244"

oder

nd = na/nb

"16281251 640250 25.4295212807"

Was nicht geht, sind _beide_ Operationen hintereinander. Offenbar vermurkse ich die Ausgangsobjekte na und/oder nb. Und was überhaupt nicht konvergiert, ist der Heron. Der erzeugt buchstäblich seitenlange Zähler und Nenner...(schamhaft _nicht_ gezeigt hier :))

Ich hänge hier an einer Stelle ab, die für Euch Python Spezies wahrscheinlich sofort erkennbar ist.

Heute vormittag ist erst mal Sonne geniessen angesagt, dann sehen wir weiter.

Grüsse
BlackJack

@spongebob.squarepants: Bei den ganzen Rechenoperationen veränderst Du erst das Objekt auf dem die aufgerufen werden und gibst dann eine Kopie zurück. Also in anderen Worten: Bei ``a = b + c`` haben nacher `a` und `b` (!) den Wert der Addition. Das ist so gar nicht das erwartete Verhalten von "Numerischen" Objekten.
BlackJack

Statt zu "klonen" könntest Du die `__init__()` etwas "freundlicher" gestalten, so dass man einen Bruch aus Zähler und Nenner erzeugen kann. Einen alternativen "Konstruktor" für Brüche aus Fliesskommazeichenketten kann man dann als `classmethod()` implementieren:

http://paste.pocoo.org/show/118815/

Ich weiss jetzt allerdings nicht, ob es Klassenmethoden schon in Python 1.5 gab. Da müsste man also im Notfall auf eine Fabrikfunktion zurückgreifen.
Benutzeravatar
Dill
User
Beiträge: 470
Registriert: Mittwoch 10. Januar 2007, 14:52
Wohnort: Köln

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

kleinlich? naja...

manche machen einen grossen unterschied zwischen kunden und interessenten.
habt ihr schon gekauft? dann wäre keine reaktion eine frechtheit.
falls nicht ist es weniger schlimm aber immernoch dumm von denen.
ich würde direkt anrufen. evtl regeln die den erstkontakt aber auch über einen distributor. muss du halt mal schauen.

du hast aber im professionellen bereich eigentlich immer einen sehr guten service den du nutzen solltest.
http://www.kinderpornos.info
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Hallo Blackjack,

ja, da sieht man mal wieder... Es war doch recht spät :) Das ist dann wohl ein Mix aus einer Vorversion mit dem letzten Versuch... Ich habe das heute morgen auch nicht mehr geblickt.. Egal.

Danke für den __init__ Tipp, probier ich mal aus.
Antworten