Wie kann eine Gleitkommazahl auf eine bestimmte Dezimalstelle gerundet werden?

83

Angenommen, ich habe 8.8333333333333339und ich möchte es konvertieren in 8.84. Wie kann ich dies in Python erreichen?

round(8.8333333333333339, 2)gibt 8.83und nicht 8.84. Ich bin neu in Python oder Programmieren im Allgemeinen.

Ich möchte es nicht als Zeichenfolge drucken, und das Ergebnis wird weiter verwendet. Weitere Informationen zum Problem finden Sie in Tim Wilsons Python-Programmiertipps: Kredit- und Zahlungsrechner .

hsinxh
quelle
4
Runde (8.83333333333333333, 2) ergibt 8,83, niemals 8,84, wie es scheint.
VGE
42
Warum 8,84? 8.8333333 ... sollte auf 8,83 gerundet werden, wenn zwei Dezimalstellen angestrebt werden.
Tim Pietzcker
1
Wenn Sie den Wert drucken möchten, verwenden Sie ein Format wie "% .2f"% 8.8333333333333339. Dies wird den Wert mit 2 Ziffern drucken
VGE
Ich habe den Titel bearbeitet, weil dies ein frühes Ergebnis für "Python Round Float" ist und es wahrscheinlich nicht das ist, wonach die meisten Leute suchen. Hoffentlich macht der neue Titel die Dinge klarer.
jpmc26

Antworten:

100

8.833333333339(oder 8.833333333333334das Ergebnis von 106.00/12) richtig auf zwei Dezimalstellen gerundet ist 8.83. Mathematisch klingt es so, als ob Sie eine Deckenfunktion wollen . Der in Pythons mathModul heißt ceil:

import math

v = 8.8333333333333339
print(math.ceil(v*100)/100)  # -> 8.84

Die Boden- und Deckenfunktionen ordnen im Allgemeinen eine reelle Zahl der größten vorherigen oder kleinsten folgenden Ganzzahl zu, die keine Dezimalstellen hat. Um sie also für 2 Dezimalstellen zu verwenden, wird die Zahl zuerst mit 10 2 multipliziert (oder 100) , um die Dezimalstelle zu verschieben Punkt und wird dann danach durch ihn geteilt, um zu kompensieren.

Wenn Sie das mathModul aus irgendeinem Grund nicht verwenden möchten , können Sie diese (minimal getestete) Implementierung verwenden, die ich gerade geschrieben habe:

def ceiling(x):
    n = int(x)
    return n if n-1 < x <= n else n+1

Wie dies auf das Problem des verknüpften Kredit- und Zahlungsrechners zutrifft

Screenshot der Ausgabe des Kreditrechners

Aus der Beispielausgabe geht hervor, dass sie die monatliche Zahlung aufgerundet haben , was viele als Effekt der Deckenfunktion bezeichnen. Dies bedeutet, dass jeden Monat etwas mehr als 112 des Gesamtbetrags gezahlt werden. Dadurch war die Restzahlung etwas geringer als gewöhnlich - und es blieb nur ein Restbetrag von unbezahlt8.76 .

Es wäre gleichermaßen gültig gewesen, eine normale Rundung zu verwenden, die eine monatliche Zahlung von 8.83und eine etwas höhere Restzahlung von ergibt 8.87. In der realen Welt möchten die Menschen jedoch im Allgemeinen nicht, dass ihre Zahlungen erhöht werden. Daher ist es üblich, jede Zahlung aufzurunden. Außerdem wird das Geld schneller an den Kreditgeber zurückgegeben.

Martineau
quelle
66

Dies ist normal (und hat nichts mit Python zu tun), da 8.83 nicht genau als binärer Float dargestellt werden kann, ebenso wie 1/3 nicht genau als Dezimalzahl dargestellt werden kann (0.333333 ... ad infinitum).

Wenn Sie absolute Präzision gewährleisten möchten, benötigen Sie das decimalModul:

>>> import decimal
>>> a = decimal.Decimal("8.833333333339")
>>> print(round(a,2))
8.83
Tim Pietzcker
quelle
Nicht, wenn Sie die printFunktion / Anweisung verwenden (abhängig von Ihrer Python-Version).
Tim Pietzcker
>>> 106.00/12 => 8.833333333333334
Martineau
22

Sie möchten das Dezimalmodul verwenden, müssen aber auch den Rundungsmodus angeben. Hier ist ein Beispiel:

>>> import decimal
>>> decimal.Decimal('8.333333').quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_UP)
Decimal('8.34')
>>> decimal.Decimal('8.333333').quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_DOWN)
Decimal('8.33')
>>> 
casevh
quelle
13

Eine viel einfachere Möglichkeit besteht darin, einfach die Funktion round () zu verwenden. Hier ist ein Beispiel.

total_price = float()
price_1 = 2.99
price_2 = 0.99
total_price = price_1 + price_2

Wenn Sie jetzt total_price ausdrucken würden, würden Sie bekommen

3.9800000000000004

Aber wenn Sie es in eine round () - Funktion wie diese einschließen

print(round(total_price,2))

Die Ausgabe ist gleich

3.98

Die Funktion round () akzeptiert zwei Parameter. Die erste ist die Zahl, die Sie runden möchten. Die zweite ist die Anzahl der Dezimalstellen, auf die gerundet werden soll.

user2252471
quelle
7

Wenn Sie 8,8333333333339 auf 2 Dezimalstellen runden, lautet die richtige Antwort 8,83 und nicht 8,84. Der Grund, warum Sie 8.83000000001 erhalten haben, ist, dass 8.83 eine Zahl ist, die in Binärform nicht korrekt wiedergegeben werden kann, und dass Sie die nächstgelegene erhalten. Wenn Sie es ohne alle Nullen drucken möchten, gehen Sie wie folgt vor:

print "%.2f" % 8.833333333339   #(Replace number with the variable?)
Andreas Løve Selvik
quelle
6

Der einfachste Weg, dies zu tun, ist die Verwendung der folgenden integrierten Funktion:

format()

Beispielsweise:

format(1.242563,".2f")

Die Ausgabe wäre:

1.24

Ähnlich:

format(9.165654,".1f")

Würde geben:

9.2
Sai Surya Madhav
quelle
Die Formatantwort wurde 2010 hier gegeben . Sie hätten diese Antwort stattdessen aktualisieren können.
ZF007
5

Wenn Sie runden möchten, ist 8,84 die falsche Antwort. 8,833333333333 gerundet ist 8,83 nicht 8,84. Wenn Sie immer aufrunden möchten, können Sie math.ceil verwenden. Führen Sie beides in Kombination mit der Formatierung von Zeichenfolgen aus, da das Runden einer Gleitkommazahl selbst keinen Sinn ergibt.

"%.2f" % (math.ceil(x * 100) / 100)
Rosh Oxymoron
quelle
4

Nur für das Protokoll. Sie könnten es so machen:

def roundno(no):
    return int(no//1 + ((no%1)/0.5)//1)

Es sind keine Einschlüsse / Importe erforderlich

Twohot
quelle
2

Hier ist meine Lösung für das Round-Up / Down-Problem

< .5  round down

> = .5  round up

import math

def _should_round_down(val: float):
    if val < 0:
        return ((val * -1) % 1) < 0.5
    return (val % 1) < 0.5

def _round(val: float, ndigits=0):
    if ndigits > 0:
        val *= 10 ** (ndigits - 1)
    is_positive = val > 0
    tmp_val = val
    if not is_positive:
        tmp_val *= -1
    rounded_value = math.floor(tmp_val) if _should_round_down(val) else math.ceil(tmp_val)
    if not is_positive:
        rounded_value *= -1
    if ndigits > 0:
        rounded_value /= 10 ** (ndigits - 1)
    return rounded_value

# test
# nr = 12.2548
# for digit in range(0, 4):
#     print("{} decimals : {} -> {}".format(digit, nr, _round(nr, digit)))

# output
# 0 decimals : 12.2548 -> 12
# 1 decimals : 12.2548 -> 12.0
# 2 decimals : 12.2548 -> 12.3
# 3 decimals : 12.2548 -> 12.25
opra
quelle
1

Ich habe diesen Code:

tax = (tax / 100) * price

und dann dieser Code:

tax = round((tax / 100) * price, 2)

Runde hat für mich funktioniert

Nic56
quelle
Du hast mein Problem gelöst. Ich konnte nur damit runden. Sonst hat nichts funktioniert. renewal_percentage=round(df_x_renewal_count/df_all_count*100)
Kierk
0

Hier ist eine einfache Funktion, um dies für Sie zu tun:

def precision(num,x):
    return "{0:.xf}".format(round(num))

Hier ist num die Dezimalzahl. x ist die Dezimalstelle bis zu der Stelle, an der Sie eine schwebende Zahl runden möchten.

Der Vorteil gegenüber anderen Implementierungen besteht darin, dass Nullen am rechten Ende der Dezimalstelle gefüllt werden können, um eine Deziamzahl mit bis zu x Dezimalstellen zu erhalten.

Beispiel 1:

precision(10.2, 9)

wird zurückkehren

10.200000000 (bis zu 9 Dezimalstellen)

Beispiel 2:

precision(10.2231, 2)

wird zurückkehren

10,22 (bis zu zwei Dezimalstellen)

Akash Kandpal
quelle