Runden von Decimal

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.
Antworten
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

Hallo,
ich versuche über getcontext().prec = 4 Decimal auf 4 Nachkommastellen zu reduzieren. Bekomme jedoch teilweise sehr verwunderlich Werte. So bekomme ich bei test1 4 Nachkommastellen, bei test2 sind es jedoch zu viele. Was hat dass denn für einen Hintergrund?

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: utf-8 -*-

from decimal import *

getcontext().prec = 4

test1 = Decimal(3.141592653) / Decimal(9)
print test1
test2 = Decimal(1.55)
print test2
BlackJack

@martinjo: Den Hintergrund kann ich Dir nicht nennen, aber in der Dokumentation im decimal — Quick-start Tutorial steht es relativ weit am Anfang, nach dem zweiten Quelltext/Beispiel-Block: „The significance of a new Decimal is determined solely by the number of digits input. Context precision and rounding only come into play during arithmetic operations.”
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Zuerst: Wenn du `Decimal` aus Fliesskommazahlen erstellst, machst du etwas falsch, da du damit die Ungenauigkeiten von Fliesskommazahlen direkt importierst.

Dein konkretes Problem ist, dass du eine wichtige Stelle in der Doku ueberlesen hast:
http://docs.python.org/2/library/decimal.html#quick-start-tutorial hat geschrieben:Context precision and rounding only come into play during arithmetic operations.
In Zeile 10 hast du, im Gegensatz zu Zeile 8, aber keine arithmetische Operation.

Zum Schluss noch: Eine Praezision von 4 Nachkommastellen ist kein Runden auf 4 Nachkommastellen. Sondern schlicht ein Rechnen mit geringerer Praezision. Sehr wahrscheinlich - schliesslich benutzt du Decimal wohl wahrscheinlich der Genauigkeit wegen, faehrst du besser, wenn du mit hoher Praezision rechnest und dann manuell auf weniger Stellen rundest.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Das getcontext().prec definiert nicht die Anzahl der Nachkommastellen einer Zahl, sondern die signifikanten Stellen während einer Berechnung im aktuellen Kontext. Beispiele:

Code: Alles auswählen

>>> Decimal('12.34') + Decimal('5678')
Decimal('5690')
>>> Decimal('12.34') + Decimal('.5678')
Decimal('12.91')
>>> Decimal('1234') + Decimal('.5678')
Decimal('1235')
>>> Decimal('1234') + Decimal('56780')
Decimal('5.801E+4')
>>> (Decimal('1234') + Decimal('56780')) / 10
Decimal('5801')
In specifications, Murphy's Law supersedes Ohm's.
BlackJack

@cofi: Vier Nachkommastellen kann durchaus gewünscht sein, zum Beispiel bei Finanzrechnungen. Da würde man `Decimal` nämlich nicht wegen einer hohen Genauigkeit verwenden, sondern gerade weil man so etwas sagen kann wie „die Rechnungen müssen mit vier signifikanten Nachkommastellen durchgeführt werden” und weil man die Kontrolle über verschiedene Arten zu runden hat. IIRC hatte martinjo hier auch schon Fragen in der Richtung wie man Finanzinformationen (Kurse, …) aus Webseiten scraped, es ist also nicht unwahrscheinlich das er tatsächlich ”wenig” Präzision und mehr Kontrolle darüber als bei `float` haben möchte. :-)
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

@BlackJack: Dass es um Geld geht hatte ich mir auch gedacht (denn geht es nicht immer um Geld...?).

@ martinjo: Decimal ist nicht nur wegen der fehlenden fixen Nachkommastellen wenig geeignet um Geldbeträge zu repräsentieren. Es gibt noch mehr Gründe:

Code: Alles auswählen

>>> from decimal import Decimal, getcontext
>>> getcontext().prec = 2
>>> my_dollars = Decimal('1000.00')
>>> my_euros = Decimal('2000.00')
>>> my_money = my_dollars + my_euros
>>> float(my_money)
3000.0
>>> i_wanna_get_rich = my_euros ** 2  # Quadrat-€
>>> float(i_wanna_get_rich)
4000000.0
Ein Web-Suche nach python "money class" sollte dir etwas passenderes als Decimal liefern.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
martinjo
User
Beiträge: 186
Registriert: Dienstag 14. Juni 2011, 20:03

Hallo

@all Danke für die vielen Antworten.

@BlackJack/pillmuncher: Ja, dass mit "getcontext().prec = 4" hatte ich falsch verstanden bzw. falsch beigebracht bekommen. Das jetzt richtig zu verstehen hilft mir schon mal viel weiter.

@cofi Das ist ein zweiter, wichtiger Punkt, Vielen Dank.
Antworten