Jeg har lavet el lille script som finder to tilfældige tal og trækker dem fra hinanden, men en sjælden gang i mellem regner den fejl: fx: 51,8 - 51,2 = 0,59999999999999 74,7 - 73,8 = 0,90000000000001
Tal1 og Tal2 er integers indtil du dividerer med 10. Så bliver de float. en float værdi har en begrænset præcision. Se http://php.net/manual/en/language.types.float.php og linket til "floating point guide".
I det aktuelle eksempel kan du løse det enten ved at vente med at dividere med 10 til du har trukket tallene fra hinanden, eller ved at udskrive facit med et antal decimaler, der er 1-2 mindre end hvad float repræsenterer.
@arne_v: Men en integer har jo også en begrænset præcision, så selv om man konverterer udregninger fra float til integer, så ender du samme sted: At der i resultatet er en begrænset præcision bestemt af antal cifre i din repræsentation af float eller integer, og af en hensigtsmæssig fremgangsmåde. Eksempelvis skal man tænke sig godt om før man trækker to næsten lige store tal fra hinanden, og regner videre derfra.
Der er stor forskel paa floating point og integer/fixed point.
Integer kan indeholde alle vaerdier som er heltal mellem min og max.
Regne operationer giver matematisk korrekte resultater medmindre man kommer udenfor min eller max.
Fixed point kan indeholde alle vaerdier som har N decimaler mellem min og max.
Regne operationer giver matematisk korrekte resultater medmindre man kommer udenfor min eller max (med visse regler for naar * og / resulterer i flere decmaler end N).
Float point indeholder et endeligt antal decimal tal med varierende antal decimaler ud af et uendeligt antal reelle tal mellem min og max.
Regne operationer giver ikke altid matematisk korrekte resultater idet resultatet nemt kan vaere et af de reelle tal som ikke kan repraesenteres eksakt.
Men disse problemer kan opstaa selv om man er paent indenfor min max intervallet.
Jeg forstår godt forskellen, men jeg har svært ved i praksis at følge den logik, at "regneoperationer giver matematisk korrekte resultater" i integer/fixed point.
Så snart du introducerer alt andet end plus og minus gælder det kun sjældent. Eksempelvis vil 1 - 1/3 - 2/3 ikke nødvendigvis give nul i fixed point.
Så min pointe er, at man i praksis skal sørge for, at ens kode tager hensyn til det - uanset om man bruger floating eller fixed point. Det gøres fx ved aldrig at checke om et udregnet tal er 0, men om den absolutte værdi er mindre end EPS (hvor EPS er et lille passende tal).
1.00 - 1.00/3.00 - 2.00/3.00 i fixed point med 2 decimaler og 4/5 afrunding er 1.00 - 0.33 - 0.67 = 0.00
1.00 - 1.00/3.00 - 2.00/3.00 i fixed point med 2 decimaler og nedrunding er 1.00 - 0.33 - 0.66 = 0.01
Man kan nogenlunde foelge resultatet.
Der burde normalt ikke vaere problemer med at lave et almindeligt == test.
1.0 - 1.0/3 - 2.0/3 i floating point er 1.0 eksakt - 1/3 plus minus en lille smule - 2/3 plus minus en lille smule = 0 plus minus en lille smule
Det er meget svaert at gennemskue hvad den "lille smule" er. Hvis man kender systemets FP format og man er villig til at lave nogle lange udregninger, saa kan det beregnes, men det er tungt.
Det vil ofte vaere problematisk at lave et alimindeligt == test.
Forstår ikke, at du skriver "Der burde normalt ikke vaere problemer med at lave et almindeligt == test". Uanset om du vælger den ene eller den anden afrunding, kan du let finde eksempler, der ikke giver 0. Fx 1- 1/3 - 1/3 - 1/3 = 1.00 - 0.33 - 0.33 - 0.33 = 0.01.
En almindelig == test er problematisk i både fixed og floating point. Derfor skal man altid benytte abs(x) < eps medmindre der er tale om integers.
Et andet praktisk problem må være, at få (jeg kender ingen) sprog tilbyder en fixed point data type.
Men det vil sjaeldent vaere grund til at betragte 0.01 som vaerende 0.
Vi har et tilfaelde hvor high level business rules (subtraktioner) og low level business rules (afrunding) giver et resultat som er forskellig fra 0. Men det er noget virkeligt som afspejler business rules. Og det vil sjaeldent give mening at ignorere det ved at betragte det som vaerende 0.
Forestil dig at det er et beloeb paa en krone som skal fordeles ligeligt til 3 personer. De faar hver 33 oerer. Saa er der 1 oere tilbage. Der er brug for en business rule som fortaeller hvordan den oere skal haandteres. Der er ikke bruge for noget software der haevder at der ikke er noget tilbage.
Hvis vi taler kroner, giver det mening. Jeg har ofte set integer brugt (og så regnes der i øre). Det giver samme effekt. Men penge er kun en begrænset del af vores verden.
Du skriver "Der er ikke bruge for noget software der haevder at der ikke er noget tilbage.". Der har du misforstået mig. Med din 1 kr der skal deles mellem 3 vil min foreslåede fremgangsmåde netop vise, at der er 1 øre tilbage, for eps skal være 1e-8 eller deromkring, og derfor er abs(rest) < eps sand.
En sidste kommentar herfra - tror vi har været rundt om emnet: Så snart du introducerer matematiske funktioner eller noget der er rundt ender du alligevel med ikke-absolutte tal. Eksempelvis kan du ikke beregne arealet af en trekant ud fra sidelængderne uden at ende der. Og så er der potentielt en residual og du kan ikke bruge ==
Penge er kun en enkelt ud af et uendeligt antal ting. Men penge er nok 95-99% af fixed point brug.
Man faar ikke fejl ved at bruge abs(x) < eps med fixed point, men det er unoedvendigt. x == 0 virker lige saa godt.
I fixed point med 2 decimaler gaar tallene ... -0.02, -0.01, 0.00, 0.01, 0.02 ....
Med fixed point med 2 decimaler vil x == 0 og abs(x) < eps altid give samme resultat for eps mindre end 0.01. Saa der er ingen grund til ikke bare at bruge ==.
(hvis eps er stoerre end 0.01 saa er fixed point med 2 decimaler naeppe et godt valg af data type)
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.