In Python auf drei Dezimalstellen kürzen

72

Wie bekomme ich 1324343032.324?

Wie Sie unten sehen können, funktioniert Folgendes nicht:

>>1324343032.324325235 * 1000 / 1000
1324343032.3243253
>>int(1324343032.324325235 * 1000) / 1000.0
1324343032.3239999
>>round(int(1324343032.324325235 * 1000) / 1000.0,3)
1324343032.3239999
>>str(1324343032.3239999)
'1324343032.32'
SuperString
quelle
4
Es gibt keinen solchen Wert in der Menge, der durch Gleitkommazahlen dargestellt wird.
Karl Knechtel
2
Für den Fall, dass Karls Kommentar nicht klar genug ist: Es gibt keine Zahl wie 1324343032.324 im binären Gleitkomma. Wenn Sie auf eine höhere Version von Python wechseln (2.7 oder 3.1 oder höher) wird der Interpret angezeigt 1324343032,324 für Sie. Tatsächlich ist die Zahl, mit der Sie rechnen, unabhängig von der Python-Version weder 1324343032.324 noch 1324343032.3239999. Die einzige Möglichkeit, genau 1324343032.324 zu erhalten , besteht darin, das decimalModul oder eine andere mathematische Bibliothek mit beliebiger Genauigkeit zu verwenden, z gmpy.
John Y
Die unten akzeptierte Antwort ist richtig, wenn Sie auf eine bestimmte Anzahl von Dezimalstellen aufrunden möchten. Die Frage stellt sich jedoch und ich wollte wissen, wie man auf eine bestimmte Anzahl von Dezimalstellen abschneidet. Für mich '%.3f'%(1324343032.3243)und '%.3f'%(1324343032.3245)geben unterschiedliche Ergebnisse. (Ich benutze Python 2.7.8).
nullstellensatz
1
@AbhranilDas diese Frage ist ein Duplikat der Frage, auf die Sie hingewiesen haben. Da beide Fragen irreführende Antworten haben, habe ich diese als Duplikat markiert, damit alle Probleme im Zusammenhang mit dem Abschneiden an einem Ort behandelt werden können. Schauen Sie sich auch meine Kommentare und Antwortvorschläge für die ursprüngliche Frage an.
nullstellensatz

Antworten:

78

Sie können ein zusätzliches float()Element verwenden, wenn Sie es als beibehalten möchtenfloat .

%.3f'%(1324343032.324325235)
Abhranil Das
quelle
4
Dies ist im Grunde die richtige Antwort, verwenden Sie einfach val = '%.3f'%(1324343032.324325235)anstelle von print.
David H. Clements
14
Diese Antwort ist richtig, wenn Sie auf eine bestimmte Anzahl von Dezimalstellen aufrunden möchten. Die Frage stellt sich jedoch und ich wollte wissen, wie man auf eine bestimmte Anzahl von Dezimalstellen abschneidet . Für mich '%.3f'%(1324343032.3243)und '%.3f'%(1324343032.3245)geben unterschiedliche Ergebnisse. (Ich benutze Python 2.7.8).
nullstellensatz
3
'% .2f'% 8866.316 ist rund, aber nicht abgeschnitten
Oleg
2
du rundest; Schauen Sie sich meine Antwort an
matsib.dev
3
Dies wird nicht abgeschnitten.
Darkenor
53

Mit der folgenden Funktion können Sie eine Zahl auf eine festgelegte Anzahl von Dezimalstellen kürzen:

import math
def truncate(number, digits) -> float:
    stepper = 10.0 ** digits
    return math.trunc(stepper * number) / stepper

Verwendung:

>>> truncate(1324343032.324325235, 3)
1324343032.324
Erwin Mayer
quelle
9
Dies sollte wirklich die akzeptierte Antwort sein. Der Code ist einfach, elegant und am sinnvollsten. Verwenden Sie die Standard-Abschneidefunktion, verschieben Sie jedoch zuerst die Dezimalstelle und verschieben Sie die Dezimalstelle nach dem Abschneiden zurück.
CatalystNZ
Beachten Sie Gleitkomma-Präzisionsfehler truncate(-1.13, 2) == -1.12, ich habe es ein wenig geändert (mit einem bitteren Geschmack im Mund) zumath.trunc(round(stepper * number, digits * 3)) / stepper
eplaut
Sie können nur int (Stepper * Nummer) / Stepper
Yohan E
16

Ich habe eine andere Lösung gefunden (sie muss effizienter sein als "String Hexerei" -Umgehungen):

>>> import decimal
# By default rounding setting in python is decimal.ROUND_HALF_EVEN
>>> decimal.getcontext().rounding = decimal.ROUND_DOWN
>>> c = decimal.Decimal(34.1499123)
# By default it should return 34.15 due to '99' after '34.14'
>>> round(c,2)
Decimal('34.14')
>>> float(round(c,2))
34.14
>>> print(round(c,2))
34.14

Über das Dezimalstellenmodul

Informationen zu Rundungseinstellungen

lösenMe
quelle
1
Ich denke, dies sollte eine der akzeptierteren Antworten sein ... es zeigt Ihnen, wie Sie Module zu Ihrem Vorteil nutzen und modifizieren können, was zum Ausdruck bringt, wie dynamisch und leistungsfähig Python sein kann
Gewächshaus
8

Wie wäre es damit:

In [1]: '%.3f' % round(1324343032.324325235 * 1000 / 1000,3)
Out[1]: '1324343032.324'

Mögliches Duplikat von round () in Python scheint nicht richtig zu runden

[BEARBEITEN]

Angesichts der zusätzlichen Kommentare, von denen ich glaube, dass Sie dies tun möchten:

In : Decimal('%.3f' % (1324343032.324325235 * 1000 / 1000))
Out: Decimal('1324343032.324')

Die Gleitkomma-Genauigkeit wird nicht das sein, was Sie wollen:

In : 3.324
Out: 3.3239999999999998

(Alle Beispiele sind mit Python 2.6.5)

AlG
quelle
7

'% .3f'% (1324343032.324325235)

Es ist nur in diesem speziellen Fall in Ordnung.

Ändern Sie einfach die Nummer ein wenig:

1324343032.324 7 25235

Und dann:

'%.3f'%(1324343032.324725235)

gibt Ihnen 1324343032.325

Versuchen Sie stattdessen Folgendes:

def trun_n_d(n,d):
    s=repr(n).split('.')
    if (len(s)==1):
        return int(s[0])
    return float(s[0]+'.'+s[1][:d])

Eine weitere Option für trun_n_d :

def trun_n_d(n,d):
    dp = repr(n).find('.') #dot position
    if dp == -1:  
        return int(n) 
    return float(repr(n)[:dp+d+1])

Noch eine andere Option (eine Oneliner- Option ) für trun_n_d [dies setzt voraus, dass ' n ' ein str und ' d ' ein int ist ]:

def trun_n_d(n,d):
    return (  n if not n.find('.')+1 else n[:n.find('.')+d+1]  )

Mit trun_n_d erhalten Sie die gewünschte Ausgabe in Python 2.7 und Python 3.6

trun_n_d (1324343032.324325235,3) gibt 1324343032.324 zurück

Ebenso trun_n_d (1324343032.324 7 25235,3) kehrt 1324343032,324


Hinweis 1 In Python 3.6 (und wahrscheinlich in Python 3.x) funktioniert so etwas einwandfrei:

def trun_n_d(n,d):
    return int(n*10**d)/10**d

Aber auf diese Weise lauert der runde Geist immer herum.

Anmerkung 2 In solchen Situationen ist es aufgrund der Anzahl der Interna von Python , wie Rundung und Ungenauigkeit , viel besser , mit n als str zu arbeiten , als das int- Gegenstück zu verwenden. Sie können Ihre Nummer am Ende jederzeit in einen Float umwandeln.

matsib.dev
quelle
6

Verwenden Sie das Dezimalmodul. Aber wenn Sie Floats verwenden müssen und sie trotzdem irgendwie in eine bestimmte Anzahl von Dezimalstellen zwingen müssen, bietet die Konvertierung in eine Zeichenfolge und einen Rücken eine (ich fürchte, ziemlich ungeschickte) Methode, dies zu tun.

>>> q = 1324343032.324325235 * 1000 / 1000
>>> a = "%.3f" % q
>>> a
'1324343032.324'
>>> b = float(a)
>>> b
1324343032.324

Damit:

float("%3.f" % q)
Primeln
quelle
1
Es ist gut, dass Sie zuerst das Dezimalmodul erwähnt haben, denn das ist die einzig vollständig richtige Antwort. Eine Sache, auf die Sie im Übrigen ein wenig achten sollten, ist, dass bin Ihrem Beispiel in Versionen von Python vor 2.7 1324343032.3239999 angezeigt wird. Und tatsächlich ist dies der Wert, den OP sieht, wenn er es versucht. Natürlich sind beide Werte in Bezug auf den binären Gleitkomma nicht zu unterscheiden.
John Y
5

Ich halte die Verwendung der formatFunktion für eine schlechte Idee. Siehe unten. Es rundet den Wert ab. Ich benutze Python 3.6.

>>> '%.3f'%(1.9999999)
'2.000'

Verwenden Sie stattdessen einen regulären Ausdruck:

>>> re.match(r'\d+.\d{3}', str(1.999999)).group(0)
'1.999'
Yiqing Lan
quelle
3

Almos Link erklärt, warum dies passiert. Verwenden Sie die Dezimalbibliothek, um das Problem zu lösen .

Spencer Rathbun
quelle
2

Vielleicht so:

def myTrunc(theNumber, theDigits):

    myDigits = 10 ** theDigits
    return (int(theNumber * myDigits) / myDigits)
OSchubert
quelle
Heads up, dies funktioniert unter Python 3, jedoch nicht unter Python 2, da sich die Funktionsweise geändert hat /.
Jeff G
2

Okay, dies ist nur ein weiterer Ansatz, um dieses Problem zu lösen, indem Sie an der Zahl als Zeichenfolge arbeiten und ein einfaches Stück davon ausführen. Dies gibt Ihnen eine abgeschnittene Ausgabe der Zahl anstelle einer gerundeten.

num = str(1324343032.324325235)
i = num.index(".")
truncated = num[:i + 4]
    
print(truncated)

Ausgabe:

'1324343032.324'

Natürlich können Sie dann analysieren:

float(truncated)
Revliscano
quelle
1

Nachdem ich nach einer Möglichkeit gesucht hatte, dieses Problem zu lösen, ohne ein Python 3-Modul oder zusätzliche mathematische Operationen zu laden, löste ich das Problem nur mit str.format () e .float (). Ich denke, dieser Weg ist schneller als die Verwendung anderer mathematischer Operationen, wie in der gängigsten Lösung. Ich brauchte eine schnelle Lösung, weil ich mit einem sehr sehr großen Datensatz arbeite und deshalb hier sehr gut funktioniert.

def truncate_number(f_number, n_decimals):
      strFormNum = "{0:." + str(n_decimals+5) + "f}"
      trunc_num = float(strFormNum.format(f_number)[:-5])
      return(trunc_num)

# Testing the 'trunc_num()' function
test_num = 1150/252
[(idx, truncate_number(test_num, idx)) for idx in range(0, 20)]

Es gibt die folgende Ausgabe zurück:

[(0, 4.0),
 (1, 4.5),
 (2, 4.56),
 (3, 4.563),
 (4, 4.5634),
 (5, 4.56349),
 (6, 4.563492),
 (7, 4.563492),
 (8, 4.56349206),
 (9, 4.563492063),
 (10, 4.5634920634),
 (11, 4.56349206349),
 (12, 4.563492063492),
 (13, 4.563492063492),
 (14, 4.56349206349206),
 (15, 4.563492063492063),
 (16, 4.563492063492063),
 (17, 4.563492063492063),
 (18, 4.563492063492063),
 (19, 4.563492063492063)]
Eduardo Alvim
quelle
0

Sie können auch verwenden:

import math

nValeur = format(float(input('Quelle valeur ?    ')), '.3f')

In Python 3.6 würde es funktionieren.

Squid0ne
quelle
0
a = 1.0123456789
dec = 3 # keep this many decimals
p = 10 # raise 10 to this power
a * 10 ** p // 10 ** (p - dec) / 10 ** dec
>>> 1.012
FFT
quelle
0

Ich denke, der beste und richtige Weg ist die Verwendung des decimalModuls.

import decimal

a = 1324343032.324325235

decimal_val = decimal.Decimal(str(a)).quantize(
   decimal.Decimal('.001'), 
   rounding=decimal.ROUND_DOWN
)
float_val = float(decimal_val)

print(decimal_val)
>>>1324343032.324

print(float_val)
>>>1324343032.324

Sie können für verschiedene Werte verwenden rounding=decimal.ROUND_DOWN, verfügbare Optionen sind ROUND_CEILING, ROUND_DOWN, ROUND_FLOOR, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_UP, und ROUND_05UP. Erläuterungen zu den einzelnen Optionen finden Sie hier in den Dokumenten .

Vladimir Prudnikov
quelle
0

Vielleicht hat sich Python seit dieser Frage geändert. Alle folgenden Punkte scheinen gut zu funktionieren

Python2.7

int(1324343032.324325235 * 1000) / 1000.0
float(int(1324343032.324325235 * 1000)) / 1000
round(int(1324343032.324325235 * 1000) / 1000.0,3)
# result for all of the above is 1324343032.324
Blueskin
quelle
0

Ich schlage die nächste Lösung vor:

def my_floor(num, precision):
   return f'{num:.{precision+1}f}'[:-1]

my_floor(1.026456,2) # 1.02

ZulusK
quelle
0

Ich versuche eine Zufallszahl zwischen 5 und 7 zu generieren und möchte sie auf 3 Dezimalstellen beschränken.

import random

num = float('%.3f' % random.uniform(5, 7))
print (num)
Amit baderia
quelle
0

Funktion

def truncate(number: float, digits: int) -> float:
    pow10 = 10 ** digits
    return number * pow10 // 1 / pow10

Testcode

f1 = 1.2666666
f2 = truncate(f1, 3)
print(f1, f2)

Ausgabe

1.2666666 1.266

Erklären

Es verschiebt die f1Zahlen digitsmal nach links, schneidet dann alle Dezimalstellen und verschiebt schließlich die Zahlen digitsmal nach rechts zurück.

Beispiel in einer Sequenz:

1.2666666 # number
1266.6666 # number * pow10
1266.0    # number * pow10 // 1
1.266     # number * pow10 // 1 / pow10
Gorandp
quelle
0

Ich entwickle eine gute Lösung, ich weiß, dass es viele IfAussagen gibt, aber es funktioniert! (Es ist nur für <1 Zahlen)

def truncate(number, digits) -> float:
    startCounting = False
    if number < 1:
      number_str = str('{:.20f}'.format(number))
      resp = ''
      count_digits = 0
      for i in range(0, len(number_str)):
        if number_str[i] != '0' and number_str[i] != '.' and number_str[i] != ',':
          startCounting = True
        if startCounting:
          count_digits = count_digits + 1
        resp = resp + number_str[i]
        if count_digits == digits:
            break
      return resp
    else:
      return number
jpdeveloper
quelle
-1
>>> float(1324343032.324325235) * float(1000) / float(1000)

1324343032.3243253

>>> round(float(1324343032.324325235) * float(1000) / float(1000), 3)

1324343032.324
Mach Meriales
quelle
1
Während dieses Code-Snippet die Frage lösen kann, hilft eine Erklärung wirklich dabei, die Qualität Ihres Beitrags zu verbessern. Denken Sie daran, dass Sie die Frage in Zukunft für Leser beantworten und diese Personen möglicherweise die Gründe für Ihren Codevorschlag nicht kennen.
DimaSan