Avatar billede michaelthomassen Nybegynder
12. august 2003 - 12:52 Der er 10 kommentarer og
1 løsning

Fejl i floor funktion ?

Jeg har opdaget at der er en fejl i floor funktionen. F.eks.

$a = 1.4;
$b = 2800;
echo "a=" . $a . " b=" . $b . " a*b=" . $a*$b . " floor(a*b)=" . floor($a*$b);

a*b giver 3920 men floor(a*b) giver 3919 ????

Jeg har prøvet at lave min egen floor funktion, som laver en round($value-0.5), men det giver samme resultat. Eneste måde jeg har kunnet få det til at virke på var at lave en round($value-0.49999).

Kan det passe at det er den eneste måde at gøre det på, eller er det mig der er helt galt på den ?
Avatar billede limemedia Nybegynder
12. august 2003 - 12:55 #1
det er faktisk ikke en fejl, men jeg kan ikke huske den gyldne forklaring hvorfor det er sådan... Det er noget med tals repræsentation i maskinen
Avatar billede jara06 Nybegynder
12. august 2003 - 13:05 #2
http://dk.php.net/manual/en/language.types.float.php

"It is quite usual that simple decimal fractions like 0.1 or 0.7 cannot be converted into their internal binary counterparts without a little loss of precision. This can lead to confusing results: for example, floor((0.1+0.7)*10) will usually return 7 instead of the expected 8 as the result of the internal representation really being something like 7.9999999999...."

(gider ik oversætte)
:)
Avatar billede michaelthomassen Nybegynder
12. august 2003 - 13:08 #3
Ok, så der er en fejl i funktionen. Spørgsmålet er så om den løsning jeg har valgt (round($value-0.4999)) er den mest optimale ?
Avatar billede erikjacobsen Ekspert
12. august 2003 - 13:10 #4
Der er formelt ikke nogen fejl. Men du kan overveje om du kan undvære
at regne med kommatal.
Avatar billede michaelthomassen Nybegynder
12. august 2003 - 13:17 #5
Det kan jeg ikke. Jeg skal kunne gange med et kommatal, og jeg har brug for resultatet som floor.
Avatar billede roenving Novice
12. august 2003 - 13:22 #6
For at tage højde for den ville jeg gå en anden vej, for vi _ved_ at fejlen er meget lille, et eks. kunne være:

(round(tal*1000))/1000

-- husk at de 'store' problemer opstår med cifre efter decimaltegnet ...
Avatar billede jakoba Nybegynder
12. august 2003 - 13:35 #7
$a = 1.4;
$b = 2800;
echo "a=" . $a . " b=" . $b . " a*b=" . $a*$b . " floor(a*b)=" . floor( (round($a*100)*$b) / 100 );

ved at rounde på $a * 100 kommer de 2 første decimale i $a med. men det er blot en måde at gøre som erikjacobsen siger: ikke regne med kommatal.
Avatar billede roenving Novice
12. august 2003 - 13:51 #8
-- altså fjerne decimalerne før udregningen og så evt. sætte dem tilbage bagefter ...
Avatar billede michaelthomassen Nybegynder
14. august 2003 - 22:09 #9
Der skal vel gives nogle point, har fået inspiration fra flere af jer, så fordel selv pointene mellem jer.
Avatar billede michaelthomassen Nybegynder
20. august 2003 - 13:36 #10
Nå, hvis ingen reagerer lukker vi spørgsmålet her.
Avatar billede tipsen Nybegynder
20. august 2003 - 14:15 #11
Som skrevet ovenfor er det et klassisk problem der bunder i at computere bruger det binære tal-system til floating point repræsentationer samtidig med at præcisionen er endelig i computeren - dermed vil vi få den slags problemer med kommatal på computeren.

Hvis der endelig skal skaleres med nogle tal som i ovenstående, vil det vel være smartere at skalere med noget som kun flytter kommaet i den binære (maskinens) repræsentation af tallet - dvs. et tal der der kan skrives som 2^x. På den måde vil man ikke ændre de betydende cifre i maskinens repræsentation af tallet! Derudover tror jeg at metoden er meget afhængig af både det tal der vælges, men også det resultat der ganges på!

Prøv eks:

$a = 1.4;
$b = 2800;
echo "a=" . $a . " b=" . $b . " a*b=" . $a*$b . " floor(a*b)=" . floor((round($a*128)*$b)/128);

Jeg ved ikke om nedenstående måske kunne være et bedre alternativ i dette tilfælde:

$eps = 1e-10;
$a = 1.4;
$b = 2800;
echo floor($a*$b+$eps);

Det er dog blot høkertricks og lige gyldigt hvilken metode der bliver foreslået, vil der nemt kunne laves eksempler som modbeviser metoden. (Ellers havde man nok også rettet op på fp-repræsentationen i computeren)
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester