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.
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:
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.
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.
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.
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 >?
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.