Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Eingabeproblem - Bin langsam ratlos

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
24.11.2003, 15:39 Uhr
~Sven
Gast


Bei folgendem Code tritt das Problem auf, dass das Programm bei der Eingabe von 0.10 und 0.20 in den else-Zweig springt (Betrag kann nicht angenommen werden). Bei allen anderen Werten (0.50, 1, 2 ...) tritt das gewünscht Ergebnis auf.

Kann mir jemand sagen warum das so ist?

C++:
float geldeinwurf(float kartenwert, struct geld *speicher)
{
    float summe=0, betrag;

    do
    {
        fflush(stdin);
        scanf("%f", &betrag);

        if(betrag==0.10)
        {
            summe+=0.10;
            speicher[0].bestand++;
            printf("\nPreis: %.2f\n", kartenwert);
            printf("Eingeworfen: %.2f\n\n", summe);
        }
        else if(betrag==0.20)
        {
            summe+=0.20;
            speicher[1].bestand++;
            printf("\nPreis: %.2f\n", kartenwert);
            printf("Eingeworfen: %.2f\n\n", summe);
        }
        else if(betrag==0.50)
        {
            summe+=0.50;
            speicher[2].bestand++;
            printf("\nPreis: %.2f\n", kartenwert);
            printf("Eingeworfen: %.2f\n\n", summe);
        }
        else if(betrag==1.00)
        {
            summe+=1.00;
            speicher[3].bestand++;
            printf("\nPreis: %.2f\n", kartenwert);
            printf("Eingeworfen: %.2f\n\n", summe);
        }
        else if(betrag==2.00)
        {
            summe+=2.00;
            speicher[4].bestand++;
            printf("\nPreis: %.2f\n", kartenwert);
            printf("Eingeworfen: %.2f\n\n", summe);
        }
        else if(betrag==5.00)
        {
            summe+=5.00;
            speicher[5].bestand++;
            printf("\nPreis: %.2f\n", kartenwert);
            printf("Eingeworfen: %.2f\n\n", summe);
        }
        else if(betrag==10.00)
        {
            summe+=10.00;
            speicher[6].bestand++;
            printf("\nPreis: %.2f\n", kartenwert);
            printf("Eingeworfen: %.2f\n\n", summe);
        }
        else if(betrag==20.00)
        {
            summe+=20.00;
            speicher[7].bestand++;
            printf("\nPreis: %.2f\n", kartenwert);
            printf("Eingeworfen: %.2f\n\n", summe);
        }
        else
        {
        printf("\n\nBetrag kann nicht angenommen werden\n\n");
            summe+=0;
            printf("\nPreis: %.2f\n", kartenwert);
            printf("Eingeworfen: %.2f\n\n", summe);
        }

    }while(summe < kartenwert);

    return(summe);
    
}



Bitte selber [CPP] Tags einfügen! - virtual

Dieser Post wurde am 24.11.2003 um 15:45 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
24.11.2003, 15:57 Uhr
0xdeadbeef
Gott
(Operator)


Wahrscheinlich ein Rundungsfehler. Mach einen Epsilon-Vergleich:

C++:
const double epsilon = 0.00001;
if(abs(betrag - 0.10) < epsilon) {
  /* betrag ist ziemlich genau 0.10 */
}


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
24.11.2003, 15:58 Uhr
Tommix



Hallo,
weil z.B 0.1 in der binären Darstellung ein periodischer Bruch ist und daher nicht exakt dargestellt werden kann. Gleitkommazahlen niemals auf Gleichheit testen!

C++:
const float eps = 0.001;
if ((wert > (soll-eps)) && (wert < (soll+eps)))
{
  // wert ist ungefähr = soll
}



Gruss, Tommix


Bearbeitung:

Da quält man sich und rackert sich ab und dann war wieder einer schneller.
Fast wie im richtigen Leben hier...


Dieser Post wurde am 24.11.2003 um 16:01 Uhr von Tommix editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
24.11.2003, 16:00 Uhr
~unbekannter
Gast


do
{
fflush(stdin);
scanf("%f", &betrag);
rewind(stdin); oder // while(getchar()!='\n');


vielleicht hilft das , habe es nicht probiert ....
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
24.11.2003, 17:46 Uhr
~gaaaaaaaaast
Gast


ich wollte nur mal sagen

fflush(stdin);

ist undefiniertes Verhalten wenn mir der link einfällt kann ich mal posten
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
24.11.2003, 18:54 Uhr
Pablo
Supertux
(Operator)



Zitat:
~Sven postete
Bei folgendem Code tritt das Problem auf, dass das Programm bei der Eingabe von 0.10 und 0.20 in den else-Zweig springt (Betrag kann nicht angenommen werden). Bei allen anderen Werten (0.50, 1, 2 ...) tritt das gewünscht Ergebnis auf.



@beefy hat Recht. Float und double lassen sich nicht so auf Genauigkeit prüfen, sondern du musst einEpsilon-Schlauch bilden, d.h. f < wert+epliso && f > wert-epsilon.
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
26.11.2003, 09:24 Uhr
~Sven
Gast


Mit dem Epsilon-Vergleich hat es geklappt.

Es gibt allerdings noch eine andere Methode.
Man kann die float Zahlen in integer umwandeln und dann die Zahlen vergleichen:

statt
if(betrag==0.10
if((int)(betrag*100)==10)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
26.11.2003, 10:24 Uhr
Tommix



Da kann, wenn du Pech hast (int)(9.9999) = 9 rauskommen.
Besser:

C++:
if ((int)(betrag*100+0.5)==10)



- Tommix
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
26.11.2003, 21:12 Uhr
Pablo
Supertux
(Operator)


Aber wenn du zum Beispiel 4.4 und 4.6 speicherst und beide sollen verglichen werden? Dann wird 4.6 und 4.4 akzeptiert, obwohl du die eine oder die andere willst. Probiera mal das!

C++:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
    float x = pow(2,32); // 2^32
    cout << (int) x << endl;
    return 0;
}



Welchen Wert wird denn ausgegeben?
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 26.11.2003 um 21:13 Uhr von Pablo Yanez Trujillo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
27.11.2003, 19:34 Uhr
~Hans-Martin
Gast


Hallo Sven,

die einfachste Lösung ist die, float als Format zu meiden und double zu verwenden. Da die Zeiten von Speichersegmenten mit 64 kB lange vorbei sind, macht es keinen Sinn, hier 4 Byte zu sparen. float ist für Abfragen generell ungeeignet, wenn es um ein wenig Präzision geht.

Ich hatte vor ein paar Jahren zusätzlich ein Problem mit der Zuweisung einer Zahl an einen float oder double-Wert, das erst verschwand, als ich in dieser Form zugewiesen habe, als Beispiel nehme ich die Zahl 17.

double a;
a=17.; <--- also ein Punkt als Zeichen für eine Dezimalzahl

Ansonsten weist Du einen int-Wert zu und es bedarf der Wandlung.

Was die anderen geschrieben haben ist natürlich auch richtig, mit Ausnahme der Feststellung, daß der Vergleich auch bei double nicht funktioniert. Er tut es.

Du mußt lediglich bei scanf als Format statt "%f" nun "%lf" verwenden.

Gruß

Hans-Martin+
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: