Avatar billede narrr Nybegynder
21. oktober 2003 - 22:15 Der er 9 kommentarer og
1 løsning

Mystisk fejl [beskrivende titel]

Nogen, der kan forklare mig, hvorfor følgende kode sommetider skriver "WRONG" selvom jeg skriver det rigtige svar?

---
int main()
{
    srand(time(NULL));
    while(1){
   
        double tal1 = (rand()%21)/10.0f;
        double tal2 = (rand()%21)/10.0f;
        double answer=0;
       

        cout << "What is: " << tal1 << " + " << tal2 << " ?" << endl;
        cin>>answer;
        if(answer == tal1+tal2)
            cout << "correct."<<endl;
        else
            cout << "wrong. It's " << tal1+tal2 << " !"<<endl;
    }
}
---
Avatar billede arne_v Ekspert
21. oktober 2003 - 22:21 #1
Gæt: det er floating point's almindelige usikerhed som gør sig gældende.

Hvis du testede på om svaret lå inden for +/- 0.00000001 så ville
det sikkert virke.
Avatar billede arne_v Ekspert
21. oktober 2003 - 22:26 #2
Jep - det er det.

Prøv det her og se forskellen:

#include <iostream>
#include <cstdlib>
#include <cmath>

using namespace std;

int main()
{
    srand(time(NULL));
    while(1){
 
        double tal1 = (rand()%21)/10.0f;
        double tal2 = (rand()%21)/10.0f;
        double answer=0;
     

        cout << "What is: " << tal1 << " + " << tal2 << " ?" << endl;
        cin>>answer;
        if(answer == tal1+tal2)
            cout << "correct."<<endl;
        else
            cout << "wrong. It's " << tal1+tal2 << " !"<<endl;
        double dif = fabs(answer - (tal1+tal2));
        if(dif < 0.000001)
            cout << "correct."<<endl;
        else
            cout << "wrong. It's " << tal1+tal2 << " !"<<endl;
    }
    return 0;
}
Avatar billede arne_v Ekspert
21. oktober 2003 - 22:26 #3
Som hoved-regel må man aldrig bruge == og != på float og double.
Avatar billede segmose Nybegynder
22. oktober 2003 - 09:10 #4
Og man skal bruge DBL_EPSILON istedet for 0.000001 (se float.h).
Avatar billede arne_v Ekspert
22. oktober 2003 - 10:18 #5
Nej - det skal man ikke.

Valget af konstant afhænger af scale og den forventede regne unøjagtighed.

Hvis man bruger DBL_EPSILON i ovenstående melder den stadigvæk fejl i
enkelte tilfælde hvor svarer er rigtigt.

Udfra at tallene maksimalt er 4 og plus ikke er slem så bør
40*DBL_EPSILON virke.
Avatar billede olennert Nybegynder
22. oktober 2003 - 10:24 #6
arne_v:

Jeg kunne godt tænke mig at lære lidt her. Hvorfor er DBL_EPSILON ikke den rigtige løsning her? Jeg kan godt se at forskellen mellem answer og (tal1+tal2) afhænger af nøjagtigheden af double operator+(double,double), men hvordan kommer man til at kende den nøjagtighed? Er det ikke netop det som DBL_EPSILON fortæller dig?
Avatar billede arne_v Ekspert
22. oktober 2003 - 11:01 #7
Nej.

DBL_EPSILON er det mindste tal hvor 1+X != 1.

P.g.a. den måde floating point tal er lavet på så skal den naturligvis
skaleres efter om man vil sammenligne tal i størrelses ordenen 1E100 eller
1 eller 1E-100.

Derudover skal man så vurdere regne unøjagtigheden. Det kan man iøvrigt
godt regne mere eksakt på. Mne det er svært.

Jeg sagde bare max. værdi er 4 og jeg sagde at regne unøjagtighed er
ihvertfald mindre en en faktor 10. Ja - den er formentlig 1 eller tæt
på for plus, men det koster ikke noget (i den her situation) at have
den lidt for høj. Derfor 40.

Stor regne unøjagtighed kommer med udtryk som:
  /(a-b)
hvor a og b er tæt på hinanden.
Avatar billede olennert Nybegynder
22. oktober 2003 - 11:04 #8
Tak. Skal jeg oprette et spørgsmål og give dig nogle point?
Avatar billede arne_v Ekspert
22. oktober 2003 - 11:09 #9
Nej.
Avatar billede narrr Nybegynder
22. oktober 2003 - 16:35 #10
Okay.
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
Kurser inden for grundlæggende programmering

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