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

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

@Blackjack: Sieht gut aus... läuft aber nicht in 1.5.2

1) /=, *=, += und -= ---> Syntax-Error
2) Schlimmer: NameError classmethod...

Hast Du eine Idee, wie man das unter 1.5.2 lauffähig macht?

Grüsse
BlackJack

@spongebob.squarepants: 1) ist leicht, da braucht man aus `a op= b` ja nur `a = a op b` machen.

2) Hm, schauen ob's da wenigstens schon `staticmethod()` gab, und wenn nicht, dann einfach eine Funktion stattdessen schreiben, bzw. eine "Methode" die nicht `self` als erstes Argument bekommt.
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

1) Klar, schon gemacht
2) Wenn Du damit meinst, einfach "classmethod" mit "staticmethod" zu ersetzen, so bleibt es beim selben Fehler.

Wenn das als "normale" Klassenmethode gebaut werden würde, so müsste man ja wohl erst das Object instantieren, um die Methode aufrufen zu können, oder?

Aber ich habe Dich wohl nicht richtig verstanden.

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

Ich habe jetzt mal Deine Source so abgeändert:

Code: Alles auswählen

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

def euclidian(a, b):
    while b:
        a, b = b, a % b
    return a
    
def from_string(floatstr):
    intpart, fraction = floatstr.split('.')
    denominator = long(10**len(fraction))
    nominator = long(intpart) * denominator + long(fraction)
    return Fraction(nominator, denominator)


class Fraction:
    def __init__(self, nominator=0, denominator=1):
        self.nominator = nominator
        self.denominator = denominator
        self.reduce()
    
#    def from_string(cls, floatstr):
#        intpart, fraction = floatstr.split('.')
#        denominator = long(10**len(fraction))
#        nominator = long(intpart) * denominator + long(fraction)
#        return cls(nominator, denominator)
    
#    from_string = staticmethod(from_string)
    
    def reduce(self):
        gcd = euclidian(self.nominator, self.denominator)
        if gcd:
            self.nominator = self.nominator / gcd
            self.denominator = self.nominator /gcd
    
    def __add__(self, other):
        return Fraction(self.nominator * other.nominator
                       + other.nominator * self.denominator,
                       self.denominator * other.denominator)
    
    def __sub__(self, other):
        return Fraction(self.nominator * other.nominator
                       - other.nominator * self.denominator,
                       self.denominator * other.denominator)
    
    def __mul__(self, other):
        return Fraction(self.nominator * other.nominator,
                       self.denominator * other.denominator)
    
    def __div__(self, other):
        return Fraction(self.nominator * other.denominator,
                       self.denominator * other.nominator)
    
    def __str__(self):
        return '%ld/%ld' % (self.nominator, self.denominator)
    
    def __float__(self):
        return float(self.nominator) / float(self.denominator)


a = from_string('65.125004')
b = from_string('2.561')

c = a * b
print c, float(c)

# 41696283811/250000000 166.785135244

d = a / b
print d, float(d)

# 16281251/640250 25.4295212807

Rate mal, wie der Output auf der Console aussieht?

16281251/6357 2561.15321693
16281251/6357 2561.15321693

Irgendwie stehe ich im Wald...
BlackJack

Schau doch mal die `reduce()`-Methode genauer an. :-)
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Hmm. Reduce kürzt doch nur. Ich meine - Du hast schon Recht. Kommentiere ich Reduce aus, stimmt es (wobei es bei "print c" wieder zu "OverflowError: long int too long to convert" kommt)
Ich sehe nicht ganz, wie Reduce das Ergebnis von mul und div "gleichmachen" kann.

Grüsse
BlackJack

Schau Dir `reduce()` nochmal *ganz* genau an. Am besten schnappst Du Dir ein Stofftier oder eine Gummiente und erkärst dem/der dann Zeile für Zeile was da passiert. :-)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Auszug aus DEINEM Code:

Code: Alles auswählen

 def reduce(self): 
        gcd = euclidian(self.nominator, self.denominator) 
        if gcd: 
            self.nominator = self.nominator / gcd 
            self.denominator = self.nominator /gcd
Mensch, das MUSST du doch selber merken! :wink:
Im übrigen ist "if gcd" überflüssig, weil der ggT niemals Null wird.
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Ach, kommt. Nun mach Euch mal keinen Spass mit Spongebob. Ist eben nur ein Schwammkopf :)

Ehrlich: Ich seh's nicht, zumindest nicht von der Idee her. Möglicherweise ist die Realisierung rottig, aber ich sehe nicht, wie ein gekürzter Bruch das Ergebnis von Multiplikation und Division nivellieren kann.

Fühle mich gerade wie bei Jauch, nach dem 3. Joker bei der 100 € Frage :)
spongebob.squarepants
User
Beiträge: 54
Registriert: Freitag 22. Mai 2009, 12:59

Arghghghg. Ich _SEHE_. Aber: Dass das MEIN Code ist, muss ich mal strikt zurückweisen. MEIN Code sagt an dieser Stelle:

Code: Alles auswählen

    def reduce(self):
        gcd = euclidian(self.n, self.d)
        if gcd != 0:
            self.n = self.n / gcd 
            self.d = self.d / gcd
So!! :)

DIESER Code (sprich: KOT) kommt von einem tollen Helferlein namens Blackjack :)

Bitte noch mal um Aufklärung bzgl. Möglichkeiten wg. classmethod und/oder staticmethod unter 1.5.2, aber ggf. ist das auch nicht mehr so wichtig.

Mache mich jetzt mal an den Heron.


Danke soweit. Jauch-Gefühl beseitigt :)
Antworten