Hei! Olen melko harrastelijatasoinen, ja olen kokeillut monia korjauksia koodiin, joten anteeksi, jos kirjoittamani koodi on hieman outoa, tyhmää (korjauksista jääneitä outouksia) tai yksinkertaista.
Olisi ongelma. Yritin tehdä yksinkertaisen ohjelman, joka arpoo "desimaalilukuja", ja käyttäjä laskee ne yhteen. 2 desimaalia. Ohjelma näyttää toimivan usein ihan hyvin, mutta sitten tuleekin tenkkapoo, ja ohjelma väittää, että annettu vastaus on väärä, vaikka ohjelma itse tulostaa vielä saman lukeman varmistukseksi. Omat taidot eivät nyt riitä käsittämään. Onko ongelma ehkä jokin tuolla desimaalijutussa.
Ja kiersin desimaaliluvun luomisen luomalla ensin "pääluvun", ja siihen summaan "kontrolloidun" desimaaliosan. Näin koska, en osannut rajoittaa desimaalin luontia 2 desimaaliin ilman pyöristys yms ongelmia.
#include <iostream> #include <stdlib.h> #include <cstdlib> #include <limits> using namespace std; double Numero(); int main() { srand(time(0)); do{ int lkm = 0; double arvo = 0; double vastaus = 0.0; double summa = 0.0; cout << "Montako numeroa?: "; cin >> lkm; cout << endl; //numeroiden tulostus ja summaus for(int i = 0; i < lkm; i++) { arvo = 0; arvo = Numero(); cout << arvo << endl; summa = summa+arvo; } cout << "\nAnna summa: "; cin >> ws >> vastaus; //vastauksen tarkistus if (vastaus != summa) { cout << "Väärin..." << endl; cout << "Oikea summa oli: " << summa << endl; } else { cout << "OIKEIN!" << endl; } cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //tällä tarvitaan vain 1 kpl cin.get() pysäytykseen cin.get(); system("clear"); }while(1); return 0; } //aliohjelma arpoo numerot. arvotaan pääluku, ja siihen ynnätään luotu desimaaliluku double Numero(){ double numero1 = 0; //pääluku double numero2 = 0; //pääluku+desimaali double desi1 = 0; //desimaalin pääluku double desi2 = 0; //josta tehdään desimaali jakamalla desi1 = (rand()%99); desi2 = desi1/100; numero1 = (rand()%10); numero2 = numero1 + desi2; return numero2; }
Esimerkkinä:
Anna summa: 10.88
Väärin...
Oikea summa oli: 10.88
Annetun summan pitäisi olla yhtä suuri ohjelman laskeman summan kanssa, mutta ohjelma on eri mieltä. Olen varmaan vain tehnyt jotain yksinkertaisen tyhmää, joka menee ohi silmien? Ensiksi luulin, että ohjelma hajoaa enter-painalluksesta, siksi siellä on tuo limits juttu. Ei ollut siinä kai ongelma. Epäilin, että sinne kuitenkin tulisi jokin "whitespace" vai miksikä kutsutaankaan, mutta ei se kai ollut ongelma. Tietenkään syötön virheentarkastusta en ole tuohon jaksanut (yrittää) tehdä, kun vain itse käyttää. Vika on varmaan tuo desimaalikyhäelmä, en vain osaa paremmin tehdä.
Lukemia, joilla väärin-ilmoitus tullut:
6.31
2
=====
8.31
0.05
3.61
=====
3.66
3.31
8.55
=====
11.86
9.84
7.65
=====
17.49
Perusongelma on se, että double ei ole tarkka (eli kaikkia lukuja ei pysty esittämään doublena ja siksi tulee pyöristysvirheitä), ja sen takia yleisesti ottaen koodissa ei koskaan pitäisi vertailla kahta doublea keskenään.
Eli käytännössä virhe on kohdassa vastaus != summa
Jos luvut ei pyöristyisi tulostuksessa, näkisit ongelman havainnollisemmin...
Esim. Anna summa: 10.88
Väärin...
Antamasi summa: 10.8800000000000000001
Oikea summa: 10.8799999999999999999
Yksi ratkaisu olisi käyttää ohjelman sisäisesti kokonaislukuja ja vaan näyttää / lukea desimaalipilkku siirrettynä.
Löytyi pari sivua, joissa sama asia on tuottanut päänvaivaa:
Näissä todetaan, että vertailu voi tuottaa epätoivottuja tuloksia ja annetaan ratkaisuehdotus, että määritetään pieni luku, epsilon, jota käytetään vertailussa (Luku1 - Luku2) < epsilon.
Kiitän suuresti vastauksistanne, tarkastelen asiaa näiden valossa, katselen, josko onnistun saamaan toimimaan! :)
TapaniS kirjoitti:
epsilon, jota käytetään vertailussa (Luku1 - Luku2) < epsilon.
Tuo ei suoraan toimi. Pitäisi olla
abs(luku1 - luku2) < epsilon
tai
(luku1 - luku2) < epsilon && (luku2 - luku1) < epsilon
Aihe on jo aika vanha, joten et voi enää vastata siihen.