Problem mit while()

OP #5925150
Warum wird das zweite while() aufgerufen???
1
double throttle = 0;
2

3
throttle_control() {
4

5
double f=0.000000;
6

7
  for(;;) { 
8

9
    if (throttle > f) {
10

11
      while(throttle > f) {         
12

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

16
      }
17

18
      while(throttle < f) {        
19

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

23
      }
24

25
    } else { 
26

27
      //wenn throttle negativ
28

29
    }
30

31
  vTaskDelay(1000 / portTICK_PERIOD_MS);
32
  }
33

34
}
35

36

37
void app_main() {
38

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

41
  throttle=30;
42

43
}
1
B 27.800000
2
B 27.900000
3
B 28.000000
4
B 28.100000
5
B 28.200000
6
B 28.300000
7
B 28.400000
8
B 28.500000
9
B 28.600000
10
B 28.700000
11
B 28.800000
12
B 28.900000
13
B 29.000000
14
B 29.100000
15
B 29.200000
16
B 29.300000
17
B 29.400000
18
B 29.500000
19
B 29.600000
20
B 29.700000
21
B 29.800000
22
B 29.900000
23
B 30.000000
24
C 29.900000
25
B 30.000000
26
C 29.900000
27
B 30.000000
28
C 29.900000
29
B 30.000000
30
C 29.900000
31
B 30.000000
32
C 29.900000
33
B 30.000000
Gast
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.
Beitrag #5925187 wurde von einem Moderator gelöscht.
Moderator
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:

1
B 0.10000000000000000555
2
B 0.20000000000000001110
3
B 0.30000000000000004441
4
B 0.40000000000000002220
5
B 0.50000000000000000000
6
B 0.59999999999999997780
7
B 0.69999999999999995559
8
B 0.79999999999999993339
9
...
10
B 29.70000000000015205615
11
B 29.80000000000015347723
12
B 29.90000000000015489832
13
B 30.00000000000015631940
14
C 29.90000000000015489832
15
B 30.00000000000015631940
16
C 29.90000000000015489832
17
B 30.00000000000015631940
Gast
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.
Gast
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.
Gast
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.
Gast
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

Eine eigene Frage? Dieser Thread ist über 7 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.