Seuraavassa kerrotaan, miten Pythonissa pyöristetään lukuja pyöristämällä tai pyöristämällä parilliseen lukuun. Lukujen oletetaan olevan liukulukutyyppiä float tai kokonaislukutyyppiä int.
- sisäänrakennettu funktio (esim. ohjelmointikielessä):
round()
- Pyöristää desimaaliluvut mihin tahansa numerolukuun.
- Pyöristää kokonaisluvut mihin tahansa numeromäärään.
- round() pyöristää parilliseen lukuun, ei yhteiseen pyöristykseen.
- standardikirjasto
decimal
quantize()
Decimal
Objektin luominen- Desimaalilukujen pyöristäminen mihin tahansa numerolukuun ja pyöristäminen parillisiin lukuihin.
- Kokonaislukujen pyöristäminen mihin tahansa numerolukuun ja pyöristäminen parillisiin lukuihin.
- Määritä uusi funktio
- Pyöristää desimaaliluvut mihin tahansa numerolukuun.
- Kokonaislukujen pyöristäminen mihin tahansa numeromäärään
- Huomautus: Negatiivisten arvojen osalta
Huomaa, että kuten edellä mainittiin, sisäänrakennettu funktio round ei ole yleinen pyöristys, vaan pyöristys parilliseen lukuun. Katso lisätietoja jäljempänä.
sisäänrakennettu funktio (esim. ohjelmointikielessä): round()
Round() on sisäänrakennettu funktio. Sitä voidaan käyttää ilman moduulien tuontia.
Ensimmäinen argumentti on alkuperäinen luku ja toinen argumentti on numeroiden määrä (kuinka moneksi numeroksi pyöristetään).
Pyöristää desimaaliluvut mihin tahansa numerolukuun.
Seuraavassa on esimerkki liukulukutyypin float käsittelystä.
Jos toinen argumentti jätetään pois, se pyöristetään kokonaisluvuksi. Tyypistä tulee myös kokonaislukutyyppi int.
f = 123.456 print(round(f)) # 123 print(type(round(f))) # <class 'int'>
Jos toinen argumentti on määritetty, se palauttaa liukulukutyypin.
Jos määritetään positiivinen kokonaisluku, määritetään desimaalipiste; jos määritetään negatiivinen kokonaisluku, määritetään kokonaislukupiste. -1 pyöristää lähimpään kymmenesosaan, -2 pyöristää lähimpään sadasosaan ja 0 pyöristää kokonaislukuun (ensimmäiseen paikkaan), mutta palauttaa float-tyypin, toisin kuin jos se jätetään pois.
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'>
Pyöristää kokonaisluvut mihin tahansa numeromäärään.
Seuraavassa on esimerkki kokonaislukutyypin int käsittelystä.
Jos toinen argumentti jätetään pois tai jos määritetään 0 tai positiivinen kokonaisluku, alkuperäinen arvo palautetaan sellaisenaan. Jos annetaan negatiivinen kokonaisluku, se pyöristetään vastaavaan kokonaislukuun. Molemmissa tapauksissa palautetaan kokonaislukutyyppinen int.
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() pyöristää parilliseen lukuun, ei yhteiseen pyöristykseen.
Huomaa, että Python 3:n sisäänrakennetulla round()-funktiolla pyöristetään parilliseen lukuun, ei yleiseen pyöristykseen.
Virallisen dokumentaation mukaan 0,5 pyöristetään 0:ksi, 5 pyöristetään 0:ksi ja niin edelleen.
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
Pyöristäminen parilliseksi luvuksi määritellään seuraavasti.
Jos murtoluku on pienempi kuin 0,5, pyöristä se alaspäin; jos murtoluku on suurempi kuin 0,5, pyöristä se ylöspäin; jos murtoluku on tasan 0,5, pyöristä se ylöspäin pyöristämisen ja alaspäin pyöristämisen välillä olevaan parilliseen lukuun.
Rounding – Wikipedia
0,5 ei ole aina typistetty.
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
Joissakin tapauksissa määritelmä pyöristämisestä parilliseen lukuun ei koske edes käsittelyä kahden desimaalin jälkeen.
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
Tämä johtuu siitä, että desimaalilukuja ei voida esittää täsmälleen liukulukuina, kuten virallisessa dokumentaatiossa todetaan.
Round():n käyttäytyminen liukuluvuille voi yllättää sinut.:Esimerkiksi round(2.675, 2) antaa tulokseksi 2.67 eikä 2.68, kuten odotettiin. Tämä ei ole virhe.:Tämä johtuu siitä, että useimpia desimaalilukuja ei voida esittää tarkasti liukuluvuilla.
round() — Built-in Functions — Python 3.10.2 Documentation
Jos haluat saada aikaan yleisen pyöristyksen tai tarkan pyöristyksen desimaaliluvuista parillisiin lukuihin, voit käyttää standardikirjaston decimal quantize -funktiota (kuvattu alla) tai määritellä uuden funktion.
Huomaa myös, että Python 2:ssa round() ei pyöristä parilliseen lukuun, vaan pyöristää.
kvantisoi() standardikirjastossa decimal
Standardikirjaston decimal-moduulia voidaan käyttää tarkkojen desimaalisten liukulukujen käsittelyyn.
Desimaalimoduulin quantize()-metodilla on mahdollista pyöristää lukuja määrittämällä pyöristystapa.
- 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
Kvantisoi()-menetelmän argumentin pyöristys asetetuilla arvoilla on seuraavat merkitykset.
ROUND_HALF_UP
:Yleinen pyöristysROUND_HALF_EVEN
:Pyöristäminen parillisiin lukuihin
Decimal-moduuli on standardikirjasto, joten lisäasennusta ei tarvita, mutta tuonti on välttämätöntä.
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN
Desimaaliobjektin luominen
Decimal() -toimintoa voidaan käyttää Decimal-tyyppisten objektien luomiseen.
Jos annat argumenttina float-tyypin, näet, miten arvoa todellisuudessa käsitellään.
print(Decimal(0.05)) # 0.05000000000000000277555756156289135105907917022705078125 print(type(Decimal(0.05))) # <class 'decimal.Decimal'>
Kuten esimerkissä näkyy, 0,05:tä ei käsitellä täsmälleen 0,05:nä. Tämä on syy siihen, miksi edellä kuvattu sisäänrakennettu funktio round() pyöristää eri arvoon kuin odotettiin desimaaliarvoille, joihin esimerkissä sisältyi 0,05.
Koska 0,5 on puolet (-1 potenssi 2:sta), se voidaan ilmaista täsmälleen binäärimuodossa.
print(Decimal(0.5)) # 0.5
Jos määrität merkkijonotyypin str float-tyypin sijasta, sitä käsitellään täsmällisen arvon Decimal-tyyppinä.
print(Decimal('0.05')) # 0.05
Desimaalilukujen pyöristäminen mihin tahansa numerolukuun ja pyöristäminen parillisiin lukuihin.
Kutsu quantize() -toimintoa Decimal-tyyppisestä objektista arvon pyöristämiseksi.
Quantize():n ensimmäinen argumentti on merkkijono, jossa on sama määrä numeroita kuin haluamasi numeroiden määrä, esimerkiksi '0.1' tai '0.01'.
Lisäksi argumentti ROUNDING määrittää pyöristystavan; jos ROUND_HALF_UP on määritetty, käytetään yleistä pyöristystä.
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
Toisin kuin sisäänrakennettu funktio round(), 0,5 pyöristetään arvoon 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
Jos argumentin pyöristys arvoksi asetetaan ROUND_HALF_EVEN, pyöristys suoritetaan parillisiin lukuihin kuten sisäänrakennetussa funktiossa round().
Kuten edellä mainittiin, jos Decimal()-metodin argumentiksi määritetään liukulukutyyppinen liukuluku, sitä käsitellään Decimal-oliona, jonka arvo vastaa liukulukutyypin todellista arvoa, joten kvantisoi()-metodin käytön tulos poikkeaa odotetusta, aivan kuten sisäänrakennettu funktio 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
Jos Decimal():n argumentti on määritetty merkkijonona, jonka tyyppi on str, sitä käsitellään Decimal-oliona, jonka arvo on täsmälleen sama, joten tulos on odotusten mukainen.
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
Koska 0,5 voidaan käsitellä oikein float-tyypillä, ei ole ongelma määrittää float-tyyppiä Decimal():n argumentiksi, kun pyöristetään kokonaisluvuksi, mutta on turvallisempaa määrittää merkkijonon str-tyyppi, kun pyöristetään desimaalilukuun.
Esimerkiksi 2,675 on itse asiassa 2,67499…. float-tyyppisenä. Jos siis haluat pyöristää kahteen desimaaliin, sinun on määritettävä merkkijono Decimal()-toiminnolle, muuten tulos poikkeaa odotetusta tuloksesta riippumatta siitä, pyöristätkö lähimpään kokonaislukuun (ROUND_HALF_UP) vai parilliseen lukuun (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
Huomaa, että quantize()-metodi palauttaa Decimal-tyyppisen luvun, joten jos haluat käyttää float-tyyppistä lukua, sinun on muunnettava se float-tyypiksi käyttämällä float()-toimintoa, muuten tapahtuu virhe.
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
Kokonaislukujen pyöristäminen mihin tahansa numerolukuun ja pyöristäminen parillisiin lukuihin.
Jos haluat pyöristää kokonaislukuun, jos annat ensimmäisenä argumenttina esimerkiksi '10', et saa haluttua tulosta.
i = 99518 print(Decimal(i).quantize(Decimal('10'), rounding=ROUND_HALF_UP)) # 99518
Tämä johtuu siitä, että quantize() suorittaa pyöristyksen Decimal-olion eksponentin mukaan, mutta Decimal('10')-olion eksponentti on 0, ei 1.
Voit määrittää mielivaltaisen eksponentin käyttämällä E:tä eksponenttijonona (esim. '1E1'). Eksponentin eksponentti voidaan tarkistaa as_tuple-metodissa.
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)
Jos haluat käyttää normaalia merkintätapaa tai jos haluat käyttää kokonaislukutyyppiä int pyöristyksen jälkeen, käytä tuloksen muuntamiseen int()-toimintoa.
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
Jos argumentin pyöristys arvoksi on asetettu ROUND_HALF_UP, suoritetaan yleinen pyöristys, esimerkiksi 5 pyöristetään arvoon 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
Ongelmia ei tietenkään ole, jos määrität sen merkkijonona.
Määritä uusi funktio
Menetelmä, jossa käytetään desimaalimoduulia, on tarkka ja turvallinen, mutta jos tyyppimuunnos ei tunnu mukavalta, voit määritellä uuden funktion yleistä pyöristystä varten.
Tähän on monia mahdollisia tapoja, esimerkiksi seuraava funktio.
def my_round(val, digit=0): p = 10 ** digit return (val * p * 2 + 1) // 2 / p
Jos sinun ei tarvitse määrittää numeroiden lukumäärää ja pyöristät aina ensimmäiseen desimaaliin, voit käyttää yksinkertaisempaa muotoa.
my_round_int = lambda x: int((x * 2 + 1) // 2)
Jos haluat olla tarkka, on turvallisempaa käyttää desimaalilukua.
Seuraavat tiedot ovat vain viitteellisiä.
Pyöristää desimaaliluvut mihin tahansa numerolukuun.
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
Toisin kuin kierroksella, 0,5:stä tulee 1 yleisen pyöristyksen mukaisesti.
print(int(my_round(0.4))) print(int(my_round(0.5))) print(int(my_round(0.6))) # 0 # 1 # 1
Kokonaislukujen pyöristäminen mihin tahansa numeromäärään
i = 99518 print(int(my_round(i, -1))) # 99520 print(int(my_round(i, -2))) # 99500 print(int(my_round(i, -3))) # 100000
Toisin kuin pyöristyksessä, 5:stä tulee 10 yleisen pyöristyksen mukaisesti.
print(int(my_round(4, -1))) print(int(my_round(5, -1))) print(int(my_round(6, -1))) # 0 # 10 # 10
Huomautus: Negatiivisten arvojen osalta
Yllä olevassa esimerkkifunktiossa -0,5 pyöristetään arvoon 0.
print(int(my_round(-0.4))) print(int(my_round(-0.5))) print(int(my_round(-0.6))) # 0 # 0 # -1
Negatiivisten arvojen pyöristämistä voidaan ajatella eri tavoin, mutta jos haluat tehdä -0,5:stä -1:n, voit muuttaa sitä esimerkiksi seuraavasti
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