mikrocontroller.net

Forum: PC-Programmierung Problem mit while()


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: W3ll S. (w3llschmidt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum wird das zweite while() aufgerufen???

double throttle = 0;

throttle_control() {

double f=0.000000;

  for(;;) { 

    if (throttle > f) {

      while(throttle > f) {         

        f+=0.100000;
        printf("B %f\n",f );

      }

      while(throttle < f) {        

        f-=0.100000;
        printf("C %f\n",f );

      }

    } else { 

      //wenn throttle negativ

    }

  vTaskDelay(1000 / portTICK_PERIOD_MS);
  }

}


void app_main() {

  xTaskCreate(&throttle_control, "throttle_control", 2048, NULL, 30, NULL);

  throttle=30;

}
B 27.800000
B 27.900000
B 28.000000
B 28.100000
B 28.200000
B 28.300000
B 28.400000
B 28.500000
B 28.600000
B 28.700000
B 28.800000
B 28.900000
B 29.000000
B 29.100000
B 29.200000
B 29.300000
B 29.400000
B 29.500000
B 29.600000
B 29.700000
B 29.800000
B 29.900000
B 30.000000
C 29.900000
B 30.000000
C 29.900000
B 30.000000
C 29.900000
B 30.000000
C 29.900000
B 30.000000
C 29.900000
B 30.000000

: Verschoben durch Moderator
Autor: Dussel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum nicht?
Durch das Hochzählen wird f größer und ist irgendwann so groß, dass f 
größer als throttle ist.

Autor: Johannes S. (jojos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rundungsfehler? Float auf Gleichheit zu vergleichen ist selten gut.

Autor: Dussel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach, jetzt verstehe ich das Problem. :D
Das kann sein.

Autor: Dr. Sommer (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Die Zahl 0.1 gibt's im Binärsystem nicht, genau so wie es 1/3 im 
Dezimalsystem nicht (mit endlich vielen Ziffern) gibt. Daher wird 
stattdessen 0.09999irgendwas genommen. Da die Ausgabe mit printf rundet, 
sieht man das nicht.

Daher wird f erst zu 29.999irgendwas (kleiner 30) und dann zu 
30,999irgendwas (größer 30). Wenn du die Zahlen mit mehr Genauigkeit 
ausgibst kannst du das nachvollziehen. Kann auch sein dass es umgekehrt 
ist mit 0.1000...irgendwas.

Merke: Bei float nie davon ausgehen dass Zahlen sich genau darstellen 
lassen. Immer bedenken dass bei wiederholter Summierung sich Fehler 
aufsummieren. Dran denken das n mal x addieren nicht gleich x*n ist. Bei 
Vergleichen immer unscharf mit Toleranzbereich rechnen; sonst bringen 
winzige Unsicherheiten das System zum Kippen. Die Abstände zwischen den 
darstellbaren Zahlen werden größer. Diese ganzen Probleme umgeht man 
übrigens, indem man fixed point rechnet.

Autor: Karl M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch ein Hinweis,

je nach Zielsystem ist sizeof(double) = sizeof(float).

Autor: W3ll S. (w3llschmidt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> 30,999irgendwas (größer 30)
> übrigens, indem man fixed point rechnet.

Danke!

Beitrag #5925187 wurde vom Autor gelöscht.
Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den von Dr. Sommer beschriebenen Effekt kannst du sichtbar machen, indem
du in den beiden printfs das Format %f in %.20f änderst und damit die
Anzahl der angezeigten Nachkommastellen erhöhst. Auf meinem PC sehen die
Ergebnisse dann so aus:

B 0.10000000000000000555
B 0.20000000000000001110
B 0.30000000000000004441
B 0.40000000000000002220
B 0.50000000000000000000
B 0.59999999999999997780
B 0.69999999999999995559
B 0.79999999999999993339
...
B 29.70000000000015205615
B 29.80000000000015347723
B 29.90000000000015489832
B 30.00000000000015631940
C 29.90000000000015489832
B 30.00000000000015631940
C 29.90000000000015489832
B 30.00000000000015631940

Autor: Ron Jeremy (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Anfängerfehler Nr 135:
Man vergleicht Fliesskommatpyen nicht mit <,> oder = sondern über ein 
delta das man aus float bildet. Das gilt auch wenn das eine ein 
Fliesskommatyp ist und der andere ein Integer, man hat dort das selbe 
Problem.

Autor: mh (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Ron Jeremy schrieb:
> Anfängerfehler Nr 135:
> Man vergleicht Fliesskommatpyen nicht mit <,> oder = sondern über ein
> delta das man aus float bildet. Das gilt auch wenn das eine ein
> Fliesskommatyp ist und der andere ein Integer, man hat dort das selbe
> Problem.

Das ist nicht sehr hilfreich. Wie will man mit dem delta vergleichen, 
wenn man nicht <, > oder == benutzen darf? Es ist auch in vielen Fällen 
in Ordnung floatVariable == 0 zu prüfen.

Autor: Ron Jeremy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mh schrieb:
> Das ist nicht sehr hilfreich. Wie will man mit dem delta vergleichen,
> wenn man nicht <, > oder == benutzen darf?
Man vergleicht nat. das Delta mit diesen Operatoren, muss man das noch 
erklären?

> Es ist auch in vielen Fällen
> in Ordnung floatVariable == 0 zu prüfen.
"In vielen Fällen" -> eben nicht, das verschlimmert das Problem noch 
mehr weil der Problemfall dann noch seltener auftritt und somit noch 
schwerer zu entdecken ist wenn man diese Sorte Probleme nicht kennt.

Das ist wie bei Threadproblemen: Funktioniert meistens ohne 
Synchronisation aber irgendwann krachts (was noch gut ist, dann sieht 
man sofort hier stimmt was nicht) oder schleichen sich seltsame Fehler 
ein (klassisches Beispiel Bankkkontoabbuchungen) und dann steht der Laie 
wie der Ochs vorm Berg und weiss nicht warum.

Besser gleich richtig machen und nicht rumpfuschen.

Autor: mh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ron Jeremy schrieb:
> mh schrieb:
>> Das ist nicht sehr hilfreich. Wie will man mit dem delta vergleichen,
>> wenn man nicht <, > oder == benutzen darf?
> Man vergleicht nat. das Delta mit diesen Operatoren, muss man das noch
> erklären?

Und wieso darf man das delta mit diesen Operatoren vergleichen und 
andere Fließkommazahlen nicht? Und wo genau besteht überhaupt ein 
Problem mit < und >?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.