2010-05-08 5 views
6

Gibt es eine Möglichkeit, die Dezimalkompartimente in Python zu erhalten?Ceil() von Decimal in Python bekommen?

>>> import decimal; 
>>> decimal.Decimal(800000000000000000001)/100000000000000000000 
Decimal('8.00000000000000000001') 
>>> math.ceil(decimal.Decimal(800000000000000000001)/100000000000000000000) 
8.0 

Mathematik rundet den Wert und gibt nicht genaue Wert

+0

Ich bin neu in Python, erst gestern begann in der Tat. Stolperte über dieses Problem in meinem zweiten Übungsprogramm (das erste war natürlich das obligatorische "Drucken Hallo, Welt!";). Daher fällt es mir schwer, die beste Antwort darauf zu beurteilen. Die decimal.Context Lösung von Matthew Flaschen hat in meinem speziellen Fall funktioniert. Aber ich würde gerne andere die beste Lösung upvote (auch für Neulinge wie mich hilfreich wäre, wenn Sie erklären können, warum ein bestimmter Ansatz funktioniert besser) und ich werde zurückkommen und akzeptieren. – Gunjan

Antwort

5
x = decimal.Decimal('8.00000000000000000000001') 
with decimal.localcontext() as ctx: 
    ctx.prec=100000000000000000 
    ctx.rounding=decimal.ROUND_CEILING 
    y = x.to_integral_exact() 
+4

Das ist gut, aber die Kontextgenauigkeit muss hier nicht geändert werden. 'to_integral_exact' nimmt auch ein'Arundung'-Argument, sodass Sie vermeiden können, dass Sie mit dem Kontext insgesamt herumspielen. –

3

du die Präzision mit tun kann und Mode-Option des Konstruktor Context Rundung.

ctx = decimal.Context(prec=1, rounding=decimal.ROUND_CEILING) 
ctx.divide(decimal.Decimal(800000000000000000001), decimal.Decimal(100000000000000000000)) 

EDIT: Sie sollten die akzeptierte Antwort zu ändern .. Obwohl die prec je nach Bedarf erhöht werden kann, ist to_integral_exact eine einfachere Lösung.

+0

perfekt :) --- abgeschlossen Charakter begrenzen --- – Gunjan

+2

@Gunjan, wenn es perfekt ist, warum nicht akzeptieren ?! –

+0

@Alex Entschuldigung musste vor 6 Minuten Timeout verlassen. Danke für die Erinnerung – Gunjan

0
>>> decimal.Context(rounding=decimal.ROUND_CEILING).quantize(
... decimal.Decimal(800000000000000000001)/100000000000000000000, 0) 
Decimal('9') 
+0

Beachten Sie, dass diese Lösung Probleme für "Dezimal" -Instanzen mit großem Wert hat: Wenn Sie beispielsweise 'c.quantize (decimal.Decimal ('1e100'), 1)' mit Ihrem Kontext 'c' versuchen, erhalten Sie eine 'InvalidOperation' Ausnahme. –

0
def decimal_ceil(x): 
    int_x = int(x) 
    if x - int_x == 0: 
     return int_x 
    return int_x + 1 
18

Der direkteste Weg, um die Decke einer Dezimal-Instanz nehmen x ist x.to_integral_exact(rounding=ROUND_CEILING) zu verwenden. Es gibt keine Notwendigkeit, sich hier mit dem Kontext zu befassen. Beachten Sie, dass dabei die Flags Inexact und Rounded gegebenenfalls gesetzt werden. Wenn Sie nicht möchten, dass die Markierungen berührt werden, verwenden Sie stattdessen x.to_integral_value(rounding=ROUND_CEILING). Beispiel:

>>> from decimal import Decimal, ROUND_CEILING 
>>> x = Decimal('-123.456') 
>>> x.to_integral_exact(rounding=ROUND_CEILING) 
Decimal('-123') 

Im Gegensatz zu den meisten der Dezimal-Methoden, die to_integral_exact und to_integral_value Methoden werden nicht durch die Genauigkeit des aktuellen Kontext beeinflusst, so dass Sie nicht über das Ändern Präzision kümmern:

>>> from decimal import getcontext 
>>> getcontext().prec = 2 
>>> x.to_integral_exact(rounding=ROUND_CEILING) 
Decimal('-123') 

By the way, in Python 3.x math.ceil funktioniert genau so, wie Sie es wollen, mit der Ausnahme, dass es eine int eher als eine Decimal Instanz zurückgibt. Das funktioniert, weil math.ceil für benutzerdefinierte Typen in Python 3 überladbar ist. In Python 2 konvertiert math.ceil einfach die Decimal Instanz in eine float zuerst, möglicherweise Informationen im Prozess zu verlieren, so dass Sie mit falschen Ergebnissen enden können.

+0

Nur der Vollständigkeit halber: in Python 2.x 'math.ceil' funktioniert nicht wie erwartet: es konvertiert dezimal in float zuerst. Deshalb 'int (ceil (D (' 1.0000000000000001 ''))) 'ergibt 1 in Python 2.x und 2 in Python 3.x –

+0

@AntonyHatchkins: Danke, guter Punkt. Ich habe diese Informationen in der Antwort bearbeitet. –

0

Verwenden Sie einfach Potenz, um dies zu machen. import math

def lo_ceil(num, potency=0): # Use 0 for multiples of 1, 1 for multiples of 10, 2 for 100 ... 
     n = num/(10.0 ** potency) 
     c = math.ceil(n) 
     return c * (10.0 ** potency) 

lo_ceil(8.0000001, 1) # return 10