logo

Flytepunktfeil i Python

Python, et mye brukt programmeringsspråk, utmerker seg i numeriske databehandlingsoppgaver, men det er ikke immunt mot utfordringene som flytekomma-aritmetikk utgjør. Flytende tall i Python er tilnærminger av reelle tall, som fører til avrundingsfeil, tap av presisjon og kanselleringer som kan kaste av seg beregninger. Vi kan oppdage disse feilene ved å se etter merkelige resultater og bruke verktøynumpy.finfo>til overvåke presisjon . Med litt forsiktighet og smarte triks kan vi det holde disse feilene i sjakk og sikre at våre Python-beregninger er pålitelige. I denne artikkelen vil vi utforske vanskelighetene med flyttallsfeil i Python .

Hva er flytende kommatall?

Flytende tall er en effektiv måte å representere reelle tall på i datamaskiner. De består av tre deler:



  • Betydelige: De faktiske sifrene som representerer nummeret (f.eks. 3,14159)
  • Eksponent: Forteller hvor mange steder signifikanden skal flyttes til venstre eller høyre (f.eks. -2 i 3,14159 x 10^-2)
  • Utgangspunkt: Vanligvis 2 for datamaskiner, bestemmer hvordan tall er representert internt

Hvorfor oppstår det flytepunktfeil?

Flytende kommafeil oppstår fordi datamaskiner lagrer reelle tall ved å bruke et begrenset antall biter, noe som fører til tilnærminger og potensielle unøyaktigheter. Flytende tall har iboende begrensninger:

  • Endelig presisjon: Bare et begrenset antall sifre kan lagres i signifikanden, noe som fører til avrundingsfeil når du representerer eksakte desimaler.
  • Tap av presisjon: Operasjoner som addisjon eller subtraksjon kan redusere presisjonen ytterligere, og forsterke effekten av avrunding.
  • Underflyt/overløp: Ekstremt små eller store tall kan falle utenfor det representable området, noe som fører til underflyt (blir null) eller flyte (blir uendelig).

Typer flytende punktfeil

a) Avrundingsfeil: Den vanligste forekommer når en nøyaktig desimal må tilnærmes for å passe til den begrensede presisjonen til en flyte.

b) Tap av presisjon: Etterfølgende operasjoner kan gradvis akkumulere avrundingsfeil, noe som fører til betydelige unøyaktigheter i sluttresultatet.



c) Katastrofal kansellering: Når du trekker fra nesten like tall med motsatte fortegn, oppheves deres signifikante sifre, og etterlater et lite og unøyaktig resultat.

d) Overløp/Underløp: Disse oppstår når beregninger overskrider det representable området av flyteverdier, noe som fører til unøyaktige eller meningsløse resultater.

Oppdager flytende punktfeil

  1. Observerer uventede resultater: Sammenligning av beregnede verdier med forventede utfall eller visualisering av data kan avsløre inkonsekvenser som ofte er forårsaket av feil.
  2. Bruke biblioteker som numpy.finfo> : Biblioteker likernumpy>gi verktøy somfinfo>for å sjekke presisjonen og begrensningene til forskjellige flytedatatyper.

Python flytepunktfeil

Her vil vi diskutere ulike typer eksempler som illustrerer flyttallsfeil i Python:



Tap av presisjon i desimal til binær konvertering

I dette eksemplet konverteres desimaltallet 0,1 til binært. På grunn av den uendelige binære utvidelsen på 0,1 brukes bare et begrenset antall biter, noe som fører til tap av presisjon.

Python3




decimal_number>=> 0.1> binary_representation>=> format>(decimal_number,>'.30f'>)># 30 decimal places> print>(f>'Decimal: {decimal_number} Binary: {binary_representation}'>)>

>

>

Produksjon:

Decimal: 0.1 Binary: 0.100000000000000005551115123126>

Avrundingsfeil

Her forventes resultatet av tillegg på 1/3 tre ganger å bli 1,0. Men på grunn av avrundingsfeil ved å representere 1/3, kan det hende at summen ikke er nøyaktig 1,0.

Python3


java-tilkobling mysql



result>=> 1.0> /> 3.0> sum_result>=> result>+> result>+> result> print>(f>'Expected Result: 1.0 Actual Result: {sum_result}'>)>

>

>

Produksjon:

Expected Result: 1.0 Actual Result: 1.0>

Akkumulative feil i iterative beregninger

Dette eksemplet viser hvordan akkumulerende feil kan oppstå i iterative beregninger. Å legge til 0,1 ti ganger vil kanskje ikke gi et eksakt resultat på 1,0 på grunn av flytepunktpresisjonsbegrensninger.

Python3




total>=> 0.0> for> i>in> range>(>10>):> >total>+>=> 0.1> print>(f>'Expected Result: 1.0 Actual Result: {total}'>)>

>

>

Produksjon:

Expected Result: 1.0 Actual Result: 0.9999999999999999>

Sammenligningsproblemer

I dette tilfellet vil det å sammenligne summen av 0,1 og 0,2 til 0,3 ikke gi det forventedeTrue>resultat på grunn av den iboende unøyaktigheten til flyttall.

Python3




a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a} b: {b} Equal: {a == b}'>)>

>

>

Produksjon:

a: 0.30000000000000004 b: 0.3 Equal: False>

Uventede resultater i beregninger

Her er subtraksjonen av1e16>fra summen(1e16 + 1)>forventes å gi 1, men på grunn av flyttallsfeil kan det hende at resultatet ikke blir nøyaktig 1.

Python3




java switch uttalelse
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a} b: {b} Equal: {a == b}'>)>

>

>

Produksjon:

Expected Result: 1 Actual Result: 0.0>

Forstå flytende punktpresisjon

Her vil vi forstå flytepunktspresisjonen: 1.2 – 1.0 Anomaly i Python-

Representasjonsutfordringer

Som det er kjent at 1,2 – 1,0 = 0,2. Men når du prøver å gjøre det samme i Python vil du overrasket over resultatene:

>>> 1,2 - 1,0>

Produksjon:

0.199999999999999996>

Dette kan betraktes som en feil i Python, men det er det ikke. Dette har lite med Python å gjøre og mye mer med hvordan den underliggende plattformen håndterer flyttall. Det er et normalt tilfelle når man håndterer flyttall internt i et system. Det er et problem som oppstår når den interne representasjonen av flyttall, som bruker et fast antall binære sifre for å representere et desimaltall. Det er vanskelig å representere noen desimaltall i binærtall, så i mange tilfeller fører det til små avrundingsfeil. Vi kjenner lignende tilfeller i desimal matematikk, mange resultater kan ikke representeres med et fast antall desimaler, for Eksempel

10 / 3 = 3.33333333.......>

I dette tilfellet, med 1,2 som eksempel, er representasjonen av 0,2 i binær 0,00110011001100110011001100…… og så videre. Det er vanskelig å lagre dette uendelige desimaltallet internt. Normalt er verdien til et flyteobjekt lagret i binært flytepunkt med en fast presisjon ( vanligvis 53 biter ). Så vi representerer 1.2 internt som,

1.0011001100110011001100110011001100110011001100110011>

Som er nøyaktig lik:

1.1999999999999999555910790149937383830547332763671875>

Håndtering av flytepunktfeil

Her vil vi diskutere forskjellige eksempler på hvordan man håndterer flyttallsfeil i Python:

Avrunding til en bestemt desimal

Ved å avrunde resultatet til en bestemt desimal (f.eks. 2), kan du redusere virkningen av små flyttallsfeil.

Python3




result>=> 1.2> -> 1.0> rounded_result>=> round>(result,>2>)> print>(f>'Original Result: {result} Rounded Result: {rounded_result}'>)>

>

>

Produksjon:

Original Result: 0.19999999999999996 Rounded Result: 0.2>

Bruke desimalklasse for høy presisjon

Dedecimal>modulen girDecimal>klasse, noe som gir høyere presisjon aritmetikk. Stille inn presisjonen medgetcontext().prec>kan hjelpe til med å administrere presisjon for spesifikke beregninger

Python3




latex tekststørrelse
from> decimal>import> Decimal, getcontext> getcontext().prec>=> 4> # Set precision to 4 decimal places> result>=> Decimal(>'1.2'>)>-> Decimal(>'1.0'>)> print>(f>'High Precision Result: {result}'>)>

>

>

Produksjon:

High Precision Result: 0.2>

Bruke brøker for eksakte representasjoner

Defractions>Modulen gjør det mulig å jobbe med eksakte brøkrepresentasjoner, og unngår flytepunktfeil.

Python3




from> fractions>import> Fraction> result>=> Fraction(>'1.2'>)>-> Fraction(>'1.0'>)> print>(f>'Exact Fractional Result: {result}'>)>

>

>

Produksjon:

Exact Fractional Result: 1/5>

Håndtering av mellomresultater med desimal

BrukeDecimal>klasse for mellomberegninger for å minimere kumulative feil før konvertering tilbake til flytende.

Python3




from> decimal>import> Decimal, getcontext> getcontext().prec>=> 6> # Set precision to 6 decimal places> intermediate_result>=> Decimal(>'1.2'>)>-> Decimal(>'1.0'>)> final_result>=> float>(intermediate_result)># Convert back to float if needed> print>(f>'Intermediate Result: {intermediate_result} Final Result: {final_result}'>)>

>

>

Produksjon:

Intermediate Result: 0.2 Final Result: 0.2>

Konklusjon

Likevel tenker du hvorfor python løser ikke dette problemet , faktisk har det ingenting med python å gjøre. Det skjer fordi det er måten den underliggende c-plattformen håndterer flyttallstall på, og til slutt med unøyaktigheten, har vi alltid skrevet ned tall som en streng med et fast antall sifre. Merk at dette er i selve naturen til binært flytende komma: dette er heller ikke en feil i Python eller C , og det er heller ikke en feil i koden din. Du vil se den samme typen oppførsel på alle språk som støtter maskinvarens flytepunkt-aritmetikk, selv om noen språk kanskje ikke viser forskjellen som standard, eller i alle utdatamoduser). Vi må vurdere denne oppførselen når vi bryr oss om matematiske problemer med nøyaktige behov eller bruker den i betingede utsagn. Kryss av flytende punkt seksjon i python-dokumentasjon for mer slik atferd.

Ofte stilte spørsmål (FAQs)

1. Hva er en flyttallsfeil i Python?

En flyttallsfeil i Python refererer til avvik mellom de forventede og faktiske resultatene når du arbeider med flyttall, som oppstår fra begrensningene ved å representere reelle tall i et binært-basert system.

2. Hvorfor gjør 1.2 - 1.0> ikke lik 0.2> i Python?

Avviket skyldes de iboende utfordringene med å representere desimaltall i binærtall. Avrundingsfeil oppstår under den interne binære representasjonen, noe som fører til uventede resultater.

3. Er flytepunktfeilen en feil i Python?

Nei, det er ikke en feil i Python. Det er et vanlig problem innen databehandling knyttet til hvordan flyttall er representert internt. Python overholder IEEE 754-standarden for flytende-komma-aritmetikk.

powershell flerlinjekommentar

4. Hvordan kan jeg runde et flyttallresultat til en bestemt desimal?

Du kan brukeround()>funksjon for å avrunde et flyttallresultat til en bestemt desimal. For eksempel,rounded_result = round(result, 2)>.

5. Hva er decimal> modul, og hvordan hjelper den med å håndtere flyttallsfeil?

Dedecimal>modulen girDecimal>klasse for aritmetikk med høyere presisjon. Innstilling av presisjon og brukDecimal>kan bidra til å redusere flyttallsfeil.