A continuació s’explica com arrodonir els nombres a Python arrodonint o arrodonint a un nombre parell. Se suposa que els nombres són de tipus float de coma flotant o enter int.
- funció integrada (per exemple, en llenguatge de programació):
round()
- Arrodoneix els decimals a qualsevol nombre de dígits.
- Arrodoneix nombres enters a qualsevol nombre de dígits.
- round() arrodoneix a un nombre parell, no a un arrodonit comú
- biblioteca estàndard
decimal
quantize()
Decimal
Creació d’un objecte- Arrodoniment de decimals a qualsevol nombre de dígits i arrodonit a nombres parells
- Arrodoniment de nombres enters a qualsevol nombre de dígits i arrodonit a nombres parells
- Definiu una nova funció
- Arrodoneix els decimals a qualsevol nombre de dígits.
- Arrodoneix nombres enters a qualsevol nombre de dígits
- Nota: per a valors negatius
Tingueu en compte que, com s’ha esmentat anteriorment, la funció integrada arrodoniment no és un arrodoniment general, sinó un arrodoniment a un nombre parell. Vegeu a continuació per obtenir més informació.
funció integrada (per exemple, en llenguatge de programació):round()
Round() es proporciona com a funció integrada. Es pot utilitzar sense importar cap mòdul.
El primer argument és el nombre original i el segon argument és el nombre de dígits (a quants dígits arrodonir).
Arrodoneix els decimals a qualsevol nombre de dígits.
El següent és un exemple de processament per al tipus flotant de coma flotant.
Si s’omet el segon argument, s’arrodoneix a un nombre enter. El tipus també es converteix en un tipus enter enter.
f = 123.456 print(round(f)) # 123 print(type(round(f))) # <class 'int'>
Si s’especifica el segon argument, retorna un tipus flotant de coma flotant.
Si s’especifica un nombre enter positiu, s’especifica la posició decimal; si s’especifica un nombre enter negatiu, s’especifica el lloc de l’enter. -1 arrodonida a la dècima més propera, -2 arrodonides a la centèsima més propera i 0 arrodonides a un nombre enter (el primer lloc), però retorna un tipus flotant, a diferència de quan s’omet.
print(round(f, 1)) # 123.5 print(round(f, 2)) # 123.46 print(round(f, -1)) # 120.0 print(round(f, -2)) # 100.0 print(round(f, 0)) # 123.0 print(type(round(f, 0))) # <class 'float'>
Arrodoneix nombres enters a qualsevol nombre de dígits.
El següent és un exemple de processament per al tipus enter int.
Si s’omet el segon argument, o si s’especifica 0 o un nombre enter positiu, el valor original es retorna tal qual. Si s’especifica un nombre enter negatiu, s’arrodoneix al dígit enter corresponent. En ambdós casos, es retorna un tipus enter enter.
i = 99518 print(round(i)) # 99518 print(round(i, 2)) # 99518 print(round(i, -1)) # 99520 print(round(i, -2)) # 99500 print(round(i, -3)) # 100000
round() arrodoneix a un nombre parell, no a un arrodonit comú
Tingueu en compte que l’arrodoniment amb la funció round() integrada a Python 3 arrodoneix a un nombre parell, no a un arrodoniment general.
Tal com està escrit a la documentació oficial, 0,5 s’arrodoneix a 0, 5 s’arrodoneix a 0 i així successivament.
print('0.4 =>', round(0.4)) print('0.5 =>', round(0.5)) print('0.6 =>', round(0.6)) # 0.4 => 0 # 0.5 => 0 # 0.6 => 1 print('4 =>', round(4, -1)) print('5 =>', round(5, -1)) print('6 =>', round(6, -1)) # 4 => 0 # 5 => 0 # 6 => 10
La definició d’arrodoniment a un nombre parell és la següent.
Si la fracció és inferior a 0,5, arrodoneix-la per baix; si la fracció és superior a 0,5, arrodoneix-la; si la fracció és exactament 0,5, arrodoniu-la al nombre parell entre l’arrodoniment cap avall i l’arrodoniment cap amunt.
Rounding – Wikipedia
0,5 no sempre està truncat.
print('0.5 =>', round(0.5)) print('1.5 =>', round(1.5)) print('2.5 =>', round(2.5)) print('3.5 =>', round(3.5)) print('4.5 =>', round(4.5)) # 0.5 => 0 # 1.5 => 2 # 2.5 => 2 # 3.5 => 4 # 4.5 => 4
En alguns casos, la definició d’arrodoniment a un nombre parell ni tan sols s’aplica al processament després de dos decimals.
print('0.05 =>', round(0.05, 1)) print('0.15 =>', round(0.15, 1)) print('0.25 =>', round(0.25, 1)) print('0.35 =>', round(0.35, 1)) print('0.45 =>', round(0.45, 1)) # 0.05 => 0.1 # 0.15 => 0.1 # 0.25 => 0.2 # 0.35 => 0.3 # 0.45 => 0.5
Això es deu al fet que els decimals no es poden representar exactament com a nombres de coma flotant, tal com s’indica a la documentació oficial.
El comportament de round() per als números de coma flotant us pot sorprendre:Per exemple, arrodonir (2,675, 2) us donarà 2,67 en lloc de 2,68 com s’esperava. Això no és un error.:Això és el resultat del fet que la majoria de decimals no es poden representar exactament amb nombres de coma flotant.
round() — Built-in Functions — Python 3.10.2 Documentation
Si voleu aconseguir un arrodoniment general o un arrodoniment precís de decimals a nombres parells, podeu utilitzar la quantificació decimal estàndard de la biblioteca (que es descriu a continuació) o definir una funció nova.
Tingueu en compte també que round() a Python 2 no s’arrodoneix a un nombre parell, sinó que arrodoneix.
quantize() del decimal de la biblioteca estàndard
El mòdul decimal de la biblioteca estàndard es pot utilitzar per gestionar nombres decimals de coma flotant exactes.
Mitjançant el mètode quantize() del mòdul decimal, és possible arrodonir nombres especificant el mode d’arrodoniment.
- decimal quantize() — Decimal fixed point and floating point arithmetic — Python 3.10.2 Documentation
- Rounding modes — Decimal fixed point and floating point arithmetic — Python 3.10.2 Documentation
Els valors establerts per a l’arrodoniment d’arguments del mètode quantize() tenen els significats següents, respectivament.
ROUND_HALF_UP
:Arrodonit generalROUND_HALF_EVEN
:Arrodonint a nombres parells
El mòdul decimal és una biblioteca estàndard, de manera que no cal cap instal·lació addicional, però cal importar-lo.
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN
Creació d’un objecte decimal
Decimal() es pot utilitzar per crear objectes de tipus Decimal.
Si especifiqueu un tipus flotant com a argument, podeu veure com es tracta realment el valor.
print(Decimal(0.05)) # 0.05000000000000000277555756156289135105907917022705078125 print(type(Decimal(0.05))) # <class 'decimal.Decimal'>
Com es mostra a l’exemple, 0,05 no es tracta exactament com a 0,05. Aquesta és la raó per la qual la funció integrada round() descrita anteriorment s’ha arrodonit a un valor diferent del que s’esperava per als valors decimals, inclòs 0,05 a l’exemple.
Com que 0,5 és la meitat (-1 potència de 2), es pot expressar exactament en notació binària.
print(Decimal(0.5)) # 0.5
Si especifiqueu el tipus de cadena str en lloc del tipus flotant, es tractarà com el tipus decimal del valor exacte.
print(Decimal('0.05')) # 0.05
Arrodoniment de decimals a qualsevol nombre de dígits i arrodonit a nombres parells
Truqueu quantize() des d’un objecte de tipus Decimal per arrodonir el valor.
El primer argument de quantize() és una cadena amb el mateix nombre de dígits que el nombre de dígits que voleu trobar, com ara ‘0,1’ o ‘0,01’.
A més, l’argument ROUNDING especifica el mode d’arrodoniment; si s’especifica ROUND_HALF_UP, s’utilitza l’arrodoniment general.
f = 123.456 print(Decimal(str(f)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)) # 123 print(Decimal(str(f)).quantize(Decimal('0.1'), rounding=ROUND_HALF_UP)) # 123.5 print(Decimal(str(f)).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) # 123.46
A diferència de la funció integrada round(), 0,5 s’arrodoneix a 1.
print('0.4 =>', Decimal(str(0.4)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)) print('0.5 =>', Decimal(str(0.5)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)) print('0.6 =>', Decimal(str(0.6)).quantize(Decimal('0'), rounding=ROUND_HALF_UP)) # 0.4 => 0 # 0.5 => 1 # 0.6 => 1
Si l’argument arrodonit s’estableix a ROUND_HALF_EVEN, l’arrodoniment es realitza a nombres parells com a la funció integrada round().
Com s’ha esmentat anteriorment, si s’especifica un tipus flotant de coma flotant com a argument de Decimal(), es tracta com un objecte Decimal amb un valor igual al valor real del tipus flotant, de manera que el resultat d’utilitzar quantize() El mètode serà diferent del que s’espera, igual que la funció integrada round().
print('0.05 =>', round(0.05, 1)) print('0.15 =>', round(0.15, 1)) print('0.25 =>', round(0.25, 1)) print('0.35 =>', round(0.35, 1)) print('0.45 =>', round(0.45, 1)) # 0.05 => 0.1 # 0.15 => 0.1 # 0.25 => 0.2 # 0.35 => 0.3 # 0.45 => 0.5 print('0.05 =>', Decimal(0.05).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.15 =>', Decimal(0.15).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.25 =>', Decimal(0.25).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.35 =>', Decimal(0.35).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.45 =>', Decimal(0.45).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) # 0.05 => 0.1 # 0.15 => 0.1 # 0.25 => 0.2 # 0.35 => 0.3 # 0.45 => 0.5
Si l’argument de Decimal() s’especifica com una cadena de tipus str, es tracta com un objecte Decimal d’aquest valor exactament, de manera que el resultat és l’esperat.
print('0.05 =>', Decimal(str(0.05)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.15 =>', Decimal(str(0.15)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.25 =>', Decimal(str(0.25)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.35 =>', Decimal(str(0.35)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) print('0.45 =>', Decimal(str(0.45)).quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)) # 0.05 => 0.0 # 0.15 => 0.2 # 0.25 => 0.2 # 0.35 => 0.4 # 0.45 => 0.4
Com que el tipus float pot gestionar correctament 0,5, no hi ha cap problema a especificar el tipus float com a argument de Decimal() quan s’arrodoni a un nombre enter, però és més segur especificar el tipus de cadena en arrodonir a un decimal.
Per exemple, 2.675 és en realitat 2.67499…. en tipus flotant. Per tant, si voleu arrodonir a dos decimals, heu d’especificar una cadena a Decimal(), en cas contrari, el resultat serà diferent del resultat esperat tant si arrodoniu al nombre sencer més proper (ROUND_HALF_UP) com a un nombre parell (ROUND_HALF_EVEN). ).
print(Decimal(2.675)) # 2.67499999999999982236431605997495353221893310546875 print(Decimal(2.675).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) # 2.67 print(Decimal(str(2.675)).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) # 2.68 print(Decimal(2.675).quantize(Decimal('0.01'), rounding=ROUND_HALF_EVEN)) # 2.67 print(Decimal(str(2.675)).quantize(Decimal('0.01'), rounding=ROUND_HALF_EVEN)) # 2.68
Tingueu en compte que el mètode quantize() retorna un nombre de tipus Decimal, de manera que si voleu operar amb un nombre de tipus flotant, haureu de convertir-lo en un tipus flotant mitjançant float(), en cas contrari es produirà un error.
d = Decimal('123.456').quantize(Decimal('0.01'), rounding=ROUND_HALF_UP) print(d) # 123.46 print(type(d)) # <class 'decimal.Decimal'> # print(1.2 + d) # TypeError: unsupported operand type(s) for +: 'float' and 'decimal.Decimal' print(1.2 + float(d)) # 124.66
Arrodoniment de nombres enters a qualsevol nombre de dígits i arrodonit a nombres parells
Si voleu arrodonir a un dígit sencer, especificant alguna cosa com “10” com a primer argument no us donarà el resultat desitjat.
i = 99518 print(Decimal(i).quantize(Decimal('10'), rounding=ROUND_HALF_UP)) # 99518
Això es deu al fet que quantize() realitza l’arrodoniment segons l’exponent de l’objecte Decimal, però l’exponent de Decimal(’10’) és 0, no 1.
Podeu especificar un exponent arbitrari utilitzant E com a cadena d’exponents (p. ex., ‘1E1’). L’exponent exponent es pot comprovar amb el mètode as_tuple.
print(Decimal('10').as_tuple()) # DecimalTuple(sign=0, digits=(1, 0), exponent=0) print(Decimal('1E1').as_tuple()) # DecimalTuple(sign=0, digits=(1,), exponent=1)
Tal com és, el resultat estarà en notació exponencial utilitzant E. Si voleu utilitzar la notació normal, o si voleu operar amb el tipus enter int després d’arrodonir, utilitzeu int() per convertir el resultat.
print(Decimal(i).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP)) # 9.952E+4 print(int(Decimal(i).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP))) # 99520 print(int(Decimal(i).quantize(Decimal('1E2'), rounding=ROUND_HALF_UP))) # 99500 print(int(Decimal(i).quantize(Decimal('1E3'), rounding=ROUND_HALF_UP))) # 100000
Si l’arrodoniment de l’argument s’estableix a ROUND_HALF_UP, es produirà un arrodoniment general, per exemple, 5 s’arrodonirà a 10.
print('4 =>', int(Decimal(4).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP))) print('5 =>', int(Decimal(5).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP))) print('6 =>', int(Decimal(6).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP))) # 4 => 0 # 5 => 10 # 6 => 10
Per descomptat, no hi ha cap problema si ho especifiqueu com a cadena.
Definiu una nova funció
El mètode d’ús del mòdul decimal és precís i segur, però si no us sentiu còmode amb la conversió de tipus, podeu definir una funció nova per aconseguir l’arrodoniment general.
Hi ha moltes maneres possibles de fer-ho, per exemple, la funció següent.
def my_round(val, digit=0): p = 10 ** digit return (val * p * 2 + 1) // 2 / p
Si no cal especificar el nombre de dígits i arrodonir sempre al primer decimal, podeu utilitzar una forma més senzilla.
my_round_int = lambda x: int((x * 2 + 1) // 2)
Si necessiteu ser precís, és més segur utilitzar decimals.
El següent és només per a referència.
Arrodoneix els decimals a qualsevol nombre de dígits.
print(int(my_round(f))) # 123 print(my_round_int(f)) # 123 print(my_round(f, 1)) # 123.5 print(my_round(f, 2)) # 123.46
A diferència de la ronda, 0,5 es converteix en 1 segons l’arrodoniment general.
print(int(my_round(0.4))) print(int(my_round(0.5))) print(int(my_round(0.6))) # 0 # 1 # 1
Arrodoneix nombres enters a qualsevol nombre de dígits
i = 99518 print(int(my_round(i, -1))) # 99520 print(int(my_round(i, -2))) # 99500 print(int(my_round(i, -3))) # 100000
A diferència de la ronda, 5 es converteix en 10 segons l’arrodoniment habitual.
print(int(my_round(4, -1))) print(int(my_round(5, -1))) print(int(my_round(6, -1))) # 0 # 10 # 10
Nota: per a valors negatius
A la funció d’exemple anterior, -0,5 s’arrodoneix a 0.
print(int(my_round(-0.4))) print(int(my_round(-0.5))) print(int(my_round(-0.6))) # 0 # 0 # -1
Hi ha diverses maneres de pensar sobre l’arrodoniment de valors negatius, però si voleu convertir -0,5 en -1, podeu modificar-lo de la següent manera, per exemple
import math def my_round2(val, digit=0): p = 10 ** digit s = math.copysign(1, val) return (s * val * p * 2 + 1) // 2 / p * s print(int(my_round2(-0.4))) print(int(my_round2(-0.5))) print(int(my_round2(-0.6))) # 0 # -1 # -1