Hallo
ich - absoluter noob ohne irgendeine Ahnung - würde/muss eine Funktion implementieren, die mir einen float auf l Nachkommastellen rundet. Das Problem ist, dass ich überall nur die Information finde, dass es dafür eine Funktion gibt - diese darf ich aber nicht benutzen. Was ich habe, ist eine Funktion, die mir eine normalisierte Dasrtellung meiner Zahl a la 0,... auspuckt. Jetzt weiß ich nicht mehr weiter.. Rechnerisch weiß ich, was passieren muss; falls die l+1-ste Stelle meines floats > 4 ist, muss ich an der xl-ten Stelle +1 rechnen, aber wie ich das jetzt technisch umsetze.. Keine Ahnung.
Falls mir jemand helfen könnte, wäre ich wirklich sehr dankbar!
Rundungsfunktion selbst schreiben
- __blackjack__
- User
- Beiträge: 13077
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@hannah01: Wie soll denn gerundet werden? So wie `round()`, oder so wie Du das im Beitrag beschreibst?
Ansonsten wäre ein Tipp da nichts mit Darstellungen zu machen sondern über ganze Zahlen zu gehen.
Ansonsten wäre ein Tipp da nichts mit Darstellungen zu machen sondern über ganze Zahlen zu gehen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
So spontan würde mir da folgendes einfallen.
Code: Alles auswählen
import math
a=3.45346
print(a)
print ("{0:.4f}".format(a))
Ob es das ist was du suchst,weiss ich natürlich nicht.
@sparrow: bei der Stringdarstellung von floats gibt es viele Fälle zu beachten.
@tonikae: nein, es wird nicht so gerundet, wie man es in der Schule lernt, sondern statistisch ausgeglichen. Und ich glaube kaum, dass wenn round nicht erlaubt ist, dieser Weg erlaubt ist.
@tonikae: nein, es wird nicht so gerundet, wie man es in der Schule lernt, sondern statistisch ausgeglichen. Und ich glaube kaum, dass wenn round nicht erlaubt ist, dieser Weg erlaubt ist.
Das zu beurteilen solltest du mal besser dem OP überlassen, anstatt hier den Klugscheisser zu spielen.Sirius3 hat geschrieben: ↑Samstag 5. Dezember 2020, 10:43 @sparrow: bei der Stringdarstellung von floats gibt es viele Fälle zu beachten.
@tonikae: nein, es wird nicht so gerundet, wie man es in der Schule lernt, sondern statistisch ausgeglichen. Und ich glaube kaum, dass wenn round nicht erlaubt ist, dieser Weg erlaubt ist.
Ich darf keine Funktion aus irgendeiner Bibliothek benutzen sondern soll alles selbst schreiben.tonikae hat geschrieben: ↑Samstag 5. Dezember 2020, 15:22Das zu beurteilen solltest du mal besser dem OP überlassen, anstatt hier den Klugscheisser zu spielen.Sirius3 hat geschrieben: ↑Samstag 5. Dezember 2020, 10:43 @sparrow: bei der Stringdarstellung von floats gibt es viele Fälle zu beachten.
@tonikae: nein, es wird nicht so gerundet, wie man es in der Schule lernt, sondern statistisch ausgeglichen. Und ich glaube kaum, dass wenn round nicht erlaubt ist, dieser Weg erlaubt ist.
Ich habe dich bereits mehrfach angezaehlt. Das ist die letzte Warnung: bei der naechsten Beschimpfung bist du raus.
Und in der Sache hat Sirius3 natuerlich eh recht. Das du das nicht erkennst, sondern stattdessen zum Angriff blaest, spricht Baende. Wer auch immer heute oder in Zukunft mit dir zusammen arbeiten muss, dem spreche ich mein tief empfundenes Mitleid aus. Rechthaberische Vollpfosten ohne Ahnung braucht keiner im Team.
Nachtrag: der TE hat das (wie zu erwarten) bestaetigt.
@hannah01: der von __blackjack__ genannte Weg ist der vielversprechenste. Wenn du aus dem gegebenen x fuer die Stelle die entsprechende Zehnerpotenz berechnest, kannst du deine Zahl damit erstmal multiplizieren. Und danach durch eine einfache Subtraktion den Rest bestimmen. Ob der dann groesser oder kleiner gleich 0.4 ist, bestimmt, ob du dann addierst oder nicht. Und danach wieder durch die Zehnerpotenz dividieren.
- DeaD_EyE
- User
- Beiträge: 1017
- Registriert: Sonntag 19. September 2010, 13:45
- Wohnort: Hagen
- Kontaktdaten:
Kaufmännisches runden ist nicht so toll.
Aber das könnte man selbst implementieren.
Zitat: https://de.wikipedia.org/wiki/Rundung#S ... hes_Runden
Aber das könnte man selbst implementieren.
Code: Alles auswählen
def kround(number, ndigits=None):
"""
Kaufmännisches runden.
"""
if ndigits is not None:
exponent = 10 ** ndigits
else:
exponent = 1
number *= exponent
number, rest = divmod(number, 1)
if rest >= 0.5:
number += 1
number /= exponent
return number
Das symmetrische Runden ist besser, wenn man z.B. Einzelwerte erst rundet und dann aufsummiert.>>> kround(3.55, 1) == round(3.55, 1)
False
>>> kround(3.54, 1) == round(3.54, 1)
True
Zitat: https://de.wikipedia.org/wiki/Rundung#S ... hes_Runden
PS: Diese Anfeindungen sind scheiße!Das kaufmännische Runden erzeugt kleine systematische Fehler, da das Aufrunden um 0,5 vorkommt, das Abrunden um 0,5 jedoch nie; das kann Statistiken geringfügig verzerren. Die mathematische Rundung rundet von der genauen Mitte zwischen zwei Ziffern immer zur nächsten geraden Ziffer auf oder ab. Dadurch wird im Mittel etwa ebenso oft auf- wie abgerundet, zumindest wenn die Ursprungszahlen stochastisch sind. (Gegenbeispiel: Sind kleine Zahlen häufiger als große, kann systematisch häufiger nach unten als nach oben gerundet werden, siehe Benfordsches Gesetz.)
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
- DeaD_EyE
- User
- Beiträge: 1017
- Registriert: Sonntag 19. September 2010, 13:45
- Wohnort: Hagen
- Kontaktdaten:
Das hätte ich wahrscheinlich sogar gemacht, wenn ich nicht einfach die Signatur von round kopiert hätte.
Dort ist komischerweise None der Standardwert, aber round ist ja in C implementiert.
Die Funktion round liefert ein int zurück, wenn ndigits ein None ist und wenn man ndigits angibt (int), bekommt man einen float.
Das hatte ich in der kround nicht implementiert und an negative Zahlen habe ich erst gar nicht gedacht.
Eine weitere Sache, die man wissen sollte, wie divmod funktioniert und speziell bei negativen Zahlen ist es etwas komisch.
Damit ich keinen Knoten im Kopf bekomme, nehme ich jetzt den Betrag (abs) und copiere vorher noch das Vorzeichen.
Das mit dem None habe ich auch drin gelassen, aber so erweitert, dass bei None immer ein Int zurückgeliefert wird.
Den Docstring habe ich zur Hälfte von Wikipedia geklaut.
Code: Alles auswählen
def kround(number, ndigits=None):
"""
Kaufmännisches runden.
Liefert einen int zurück, wenn
ndigits == None
Ansonsten gibt ndigits die
Stellen hinter dem Komma an und
ein Float wird zurück gegeben.
Das Kaufmännische Runden (nicht negativer Zahlen) geschieht wie folgt:
- Ist die Ziffer an der ersten wegfallenden
Dezimalstelle eine 0, 1, 2, 3 oder 4,
dann wird abgerundet.
- Ist die Ziffer an der ersten wegfallenden
Dezimalstelle eine 5, 6, 7, 8 oder 9,
dann wird aufgerundet.
13.3749 € ≈ 13.37 €
13.3750 € ≈ 13.38 €
>>> kround(13.3749, 2)
13.37
>>> kround(13.3750, 2)
13.38
Negative Zahlen werden nach ihrem Betrag gerundet,
bei einer 5 also weg von null (engl: Away from Zero)
-13.3749 € ≈ -13.37 €
-13.3750 € ≈ -13.38 €
>>> kround(-13.3749, 2)
-13.37
>>> kround(-13.3750, 2)
-13.38
Diese Rundungsregel wird durch die Norm DIN 1333 beschrieben.
"""
sign = -1 if number < 0 else 1
if ndigits is not None:
exponent = 10 ** ndigits
else:
exponent = 1
number *= exponent
number, rest = divmod(abs(number), 1)
if rest >= 0.5:
number += 1
number /= exponent
number *= sign
if ndigits is None:
return int(number)
else:
return number
PS: Wer mag, kann ja ein Unittest schreiben. Aber Anfänger wollen sich wahrscheinlich damit nicht so lange aufhalten.
PPS: ndigits könnte auch negativ sein. Auch nicht getestet
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
@DeaD_EyE: Die Unittests sind schon da, man muss sie nur ausführen:
Code: Alles auswählen
python -m doctest kround.py
- DeaD_EyE
- User
- Beiträge: 1017
- Registriert: Sonntag 19. September 2010, 13:45
- Wohnort: Hagen
- Kontaktdaten:
Leider falsche Einrückung, und deswegen sind die Doctests kaputt.
Habs mal korrigiert, aber doctests ersetzen keine Unittests und das sollte man sich nicht darauf verlassen.
Da ich sie aber reingeschrieben habe, hätte ich es auch gleich testen sollen.
Jedenfalls habe ich jetzt behalten, dass es die DIN 1333 ist.
Habs mal korrigiert, aber doctests ersetzen keine Unittests und das sollte man sich nicht darauf verlassen.
Da ich sie aber reingeschrieben habe, hätte ich es auch gleich testen sollen.
Jedenfalls habe ich jetzt behalten, dass es die DIN 1333 ist.
Code: Alles auswählen
def kround(number, ndigits=None):
"""
Kaufmännisches runden.
Liefert einen int zurück, wenn
ndigits == None
Ansonsten gibt ndigits die
Stellen hinter dem Komma an und
ein Float wird zurück gegeben.
Das Kaufmännische Runden (nicht negativer Zahlen) geschieht wie folgt:
- Ist die Ziffer an der ersten wegfallenden
Dezimalstelle eine 0, 1, 2, 3 oder 4,
dann wird abgerundet.
- Ist die Ziffer an der ersten wegfallenden
Dezimalstelle eine 5, 6, 7, 8 oder 9,
dann wird aufgerundet.
13.3749 € ≈ 13.37 €
13.3750 € ≈ 13.38 €
>>> kround(13.3749, 2)
13.37
>>> kround(13.3750, 2)
13.38
Negative Zahlen werden nach ihrem Betrag gerundet,
bei einer 5 also weg von null (engl: Away from Zero)
-13.3749 € ≈ -13.37 €
-13.3750 € ≈ -13.38 €
>>> kround(-13.3749, 2)
-13.37
>>> kround(-13.3750, 2)
-13.38
>>> kround(99.9, -1)
100.0
>>> kround(123.123456789, 8)
123.12345679
>>> kround(123.123456789, 9)
123.123456789
>>> kround(13.50)
14
Diese Rundungsregel wird durch die Norm DIN 1333 beschrieben.
"""
sign = -1 if number < 0 else 1
if ndigits is not None:
exponent = 10 ** ndigits
else:
exponent = 1
number *= exponent
number, rest = divmod(abs(number), 1)
if rest >= 0.5:
number += 1
number /= exponent
number *= sign
if ndigits is None:
return int(number)
else:
return number
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
etwas kompakter:
Code: Alles auswählen
def kround(number, ndigits=None):
sign = -1 if number < 0 else 1
exponent = 10 ** (ndigits or 0)
number = int(number * 2 * exponent)
number = (number + sign * (number % 2)) // 2
return number if ndigits is None else number / exponent