C Float Variable mit simpler Rechnung wird schnell ungenau

Fischy33

Cadet 4th Year
Registriert
Mai 2013
Beiträge
66
Hallo zusammen,
ich brauche für ein Programm eine Zeit die von 0 hochzählt, und zwar in 0,01er Schritten.
der Code sieht dann so aus:

float t=0;
while (x<0){
...
t=t+0.01;
...
printf(datei,"%f Sekunden\n",t);
...
}
Soweit sogut, aber mein Ergebnis in der Datei sieht dann so aus:
0.010000 Sekunden
0.020000 Sekunden
0.030000 Sekunden
0.040000 Sekunden
0.050000 Sekunden
0.060000 Sekunden
0.070000 Sekunden
0.080000 Sekunden
0.090000 Sekunden
0.100000 Sekunden
0.110000 Sekunden
0.120000 Sekunden
0.130000 Sekunden
0.140000 Sekunden
0.150000 Sekunden
0.160000 Sekunden
0.170000 Sekunden
0.180000 Sekunden
0.190000 Sekunden
0.200000 Sekunden
0.210000 Sekunden
0.220000 Sekunden
0.230000 Sekunden
0.240000 Sekunden
0.250000 Sekunden
0.260000 Sekunden
0.270000 Sekunden
0.280000 Sekunden
0.290000 Sekunden
0.300000 Sekunden
0.310000 Sekunden
0.320000 Sekunden
0.330000 Sekunden
0.340000 Sekunden
0.350000 Sekunden
0.360000 Sekunden
0.370000 Sekunden
0.380000 Sekunden
0.390000 Sekunden
0.400000 Sekunden
0.410000 Sekunden
0.420000 Sekunden
0.430000 Sekunden
0.440000 Sekunden
0.450000 Sekunden
0.460000 Sekunden
0.470000 Sekunden
0.480000 Sekunden
0.490000 Sekunden
0.500000 Sekunden
0.510000 Sekunden
0.520000 Sekunden
0.530000 Sekunden
0.540000 Sekunden
0.550000 Sekunden
0.560000 Sekunden
0.570000 Sekunden
0.580000 Sekunden
0.590000 Sekunden
0.600000 Sekunden
0.610000 Sekunden
0.620000 Sekunden
0.630000 Sekunden
0.640000 Sekunden
0.650000 Sekunden
0.660000 Sekunden
0.670000 Sekunden
0.680000 Sekunden
0.690000 Sekunden
0.700000 Sekunden
0.710000 Sekunden
0.720000 Sekunden
0.730000 Sekunden
0.740000 Sekunden
0.750000 Sekunden
0.760000 Sekunden
0.770000 Sekunden
0.780000 Sekunden
0.790000 Sekunden
0.800000 Sekunden
0.810000 Sekunden
0.820000 Sekunden
0.830000 Sekunden
0.839999 Sekunden
0.849999 Sekunden
0.859999 Sekunden
0.869999 Sekunden
0.879999 Sekunden
0.889999 Sekunden
0.899999 Sekunden
0.909999 Sekunden
0.919999 Sekunden
0.929999 Sekunden
0.939999 Sekunden
0.949999 Sekunden
0.959999 Sekunden
0.969999 Sekunden
0.979999 Sekunden
0.989999 Sekunden
0.999999 Sekunden
1.009999 Sekunden
1.019999 Sekunden
1.029999 Sekunden
1.039999 Sekunden
1.049999 Sekunden
1.059999 Sekunden
1.069999 Sekunden
1.079999 Sekunden
1.089999 Sekunden
1.099999 Sekunden
1.109999 Sekunden
1.119999 Sekunden
1.129999 Sekunden
1.139999 Sekunden
1.149999 Sekunden
1.159999 Sekunden
1.169999 Sekunden
1.179999 Sekunden
1.189999 Sekunden
1.199999 Sekunden
1.209999 Sekunden
1.219999 Sekunden
1.229999 Sekunden
1.239999 Sekunden
1.249999 Sekunden
1.259999 Sekunden
1.269999 Sekunden
1.279999 Sekunden
1.289999 Sekunden
1.299999 Sekunden
1.309999 Sekunden
1.319999 Sekunden
1.329999 Sekunden
1.339999 Sekunden
1.349999 Sekunden
1.359999 Sekunden
1.369999 Sekunden
1.379999 Sekunden
1.389999 Sekunden
1.399999 Sekunden
1.409999 Sekunden
1.419999 Sekunden
1.429999 Sekunden
1.439999 Sekunden
1.449999 Sekunden
1.459999 Sekunden
1.469999 Sekunden
1.479999 Sekunden
1.489999 Sekunden
1.499999 Sekunden
1.509999 Sekunden
1.519999 Sekunden
1.529999 Sekunden
1.539999 Sekunden
1.549999 Sekunden
1.559999 Sekunden
1.569999 Sekunden
1.579999 Sekunden
1.589999 Sekunden
1.599999 Sekunden
1.609999 Sekunden
1.619999 Sekunden
1.629999 Sekunden
1.639999 Sekunden
1.649999 Sekunden
1.659999 Sekunden
1.669999 Sekunden
1.679999 Sekunden
1.689999 Sekunden
1.699999 Sekunden
1.709999 Sekunden
1.719999 Sekunden
1.729999 Sekunden
1.739999 Sekunden
1.749999 Sekunden
1.759999 Sekunden
1.769999 Sekunden
1.779999 Sekunden
1.789999 Sekunden
1.799999 Sekunden
1.809999 Sekunden
1.819999 Sekunden
1.829999 Sekunden
1.839999 Sekunden
1.849999 Sekunden
1.859999 Sekunden
1.869999 Sekunden
1.879999 Sekunden
1.889999 Sekunden
1.899999 Sekunden
1.909999 Sekunden
1.919999 Sekunden
1.929999 Sekunden
1.939999 Sekunden
1.949998 Sekunden
1.959998 Sekunden
1.969998 Sekunden
1.979998 Sekunden
1.989998 Sekunden
1.999998 Sekunden
2.009999 Sekunden
2.019999 Sekunden
2.029999 Sekunden
2.039999 Sekunden
2.049999 Sekunden
2.059999 Sekunden
2.069999 Sekunden
2.079998 Sekunden
2.089998 Sekunden
2.099998 Sekunden
2.109998 Sekunden
2.119998 Sekunden
2.129998 Sekunden
2.139998 Sekunden
2.149998 Sekunden
2.159998 Sekunden
2.169998 Sekunden
2.179998 Sekunden
2.189998 Sekunden
2.199998 Sekunden
2.209998 Sekunden
2.219998 Sekunden
2.229998 Sekunden
2.239998 Sekunden
2.249998 Sekunden
2.259998 Sekunden
2.269998 Sekunden
2.279998 Sekunden
2.289998 Sekunden
2.299998 Sekunden
2.309998 Sekunden
2.319998 Sekunden
2.329998 Sekunden
2.339998 Sekunden
2.349998 Sekunden
2.359998 Sekunden
2.369998 Sekunden
2.379998 Sekunden
2.389998 Sekunden
2.399998 Sekunden
2.409998 Sekunden
2.419998 Sekunden
2.429998 Sekunden
2.439998 Sekunden
2.449998 Sekunden
2.459998 Sekunden
2.469998 Sekunden
2.479998 Sekunden
2.489998 Sekunden
2.499998 Sekunden
2.509998 Sekunden
2.519998 Sekunden
2.529998 Sekunden
2.539998 Sekunden
2.549998 Sekunden
2.559998 Sekunden
2.569998 Sekunden
2.579998 Sekunden
2.589998 Sekunden
2.599998 Sekunden
2.609998 Sekunden
2.619998 Sekunden
2.629998 Sekunden
2.639998 Sekunden
2.649998 Sekunden
2.659998 Sekunden
2.669998 Sekunden
2.679998 Sekunden
2.689998 Sekunden
2.699998 Sekunden
2.709998 Sekunden
2.719998 Sekunden
2.729998 Sekunden
2.739998 Sekunden
2.749998 Sekunden
2.759998 Sekunden
2.769998 Sekunden
2.779998 Sekunden
2.789998 Sekunden
2.799998 Sekunden
2.809998 Sekunden
2.819998 Sekunden
2.829998 Sekunden
2.839998 Sekunden
2.849998 Sekunden
2.859998 Sekunden
2.869998 Sekunden
2.879998 Sekunden
2.889998 Sekunden
2.899998 Sekunden
2.909998 Sekunden
2.919998 Sekunden
2.929998 Sekunden
2.939998 Sekunden
2.949998 Sekunden
2.959998 Sekunden
2.969998 Sekunden
2.979998 Sekunden
2.989998 Sekunden
2.999998 Sekunden
3.009998 Sekunden
3.019998 Sekunden
3.029998 Sekunden
3.039998 Sekunden
3.049998 Sekunden
3.059998 Sekunden
3.069998 Sekunden
3.079998 Sekunden
3.089998 Sekunden
3.099998 Sekunden
3.109998 Sekunden
3.119998 Sekunden
3.129997 Sekunden
3.139997 Sekunden
3.149997 Sekunden
3.159997 Sekunden
3.169997 Sekunden
3.179997 Sekunden
3.189997 Sekunden
3.199997 Sekunden
3.209997 Sekunden
3.219997 Sekunden
3.229997 Sekunden
3.239997 Sekunden
3.249997 Sekunden
3.259997 Sekunden
3.269997 Sekunden
3.279997 Sekunden
3.289997 Sekunden
3.299997 Sekunden
3.309997 Sekunden
3.319997 Sekunden
3.329997 Sekunden
3.339997 Sekunden
3.349997 Sekunden
3.359997 Sekunden
3.369997 Sekunden
3.379997 Sekunden
3.389997 Sekunden
3.399997 Sekunden
3.409997 Sekunden
3.419997 Sekunden
3.429997 Sekunden
3.439997 Sekunden
3.449997 Sekunden
3.459997 Sekunden
3.469997 Sekunden
3.479997 Sekunden
3.489997 Sekunden
3.499997 Sekunden
3.509997 Sekunden
3.519997 Sekunden
3.529997 Sekunden
3.539997 Sekunden
3.549997 Sekunden
3.559997 Sekunden
3.569997 Sekunden
3.579997 Sekunden
3.589997 Sekunden
3.599997 Sekunden
3.609997 Sekunden
3.619997 Sekunden
3.629997 Sekunden
3.639997 Sekunden
3.649997 Sekunden
3.659997 Sekunden
3.669997 Sekunden
3.679997 Sekunden
3.689997 Sekunden
3.699997 Sekunden
3.709997 Sekunden
3.719997 Sekunden
3.729997 Sekunden
3.739997 Sekunden
3.749997 Sekunden
3.759997 Sekunden
3.769997 Sekunden
3.779997 Sekunden
3.789997 Sekunden
3.799997 Sekunden
3.809997 Sekunden
3.819997 Sekunden
3.829997 Sekunden
3.839997 Sekunden
3.849997 Sekunden
3.859997 Sekunden
3.869997 Sekunden
3.879997 Sekunden
3.889997 Sekunden
3.899997 Sekunden
3.909997 Sekunden
3.919997 Sekunden
3.929997 Sekunden
3.939997 Sekunden
3.949997 Sekunden
3.959997 Sekunden
3.969997 Sekunden
3.979997 Sekunden
3.989997 Sekunden
3.999997 Sekunden
4.009997 Sekunden
4.019997 Sekunden
4.029997 Sekunden
4.039998 Sekunden
4.049998 Sekunden
4.059998 Sekunden
4.069998 Sekunden
4.079998 Sekunden
4.089999 Sekunden
4.099999 Sekunden
4.109999 Sekunden
4.119999 Sekunden
4.130000 Sekunden
4.140000 Sekunden
4.150000 Sekunden
4.160000 Sekunden
4.170001 Sekunden
4.180001 Sekunden
4.190001 Sekunden
4.200001 Sekunden
4.210001 Sekunden
4.220002 Sekunden
4.230002 Sekunden
4.240002 Sekunden
4.250002 Sekunden
4.260003 Sekunden
4.270003 Sekunden
4.280003 Sekunden
4.290003 Sekunden
4.300004 Sekunden
4.310004 Sekunden
4.320004 Sekunden
4.330004 Sekunden
4.340004 Sekunden
4.350005 Sekunden
4.360005 Sekunden
4.370005 Sekunden
4.380005 Sekunden
4.390006 Sekunden
4.400006 Sekunden
4.410006 Sekunden
4.420006 Sekunden
4.430007 Sekunden
4.440007 Sekunden
4.450007 Sekunden
4.460007 Sekunden
4.470007 Sekunden
4.480008 Sekunden
4.490008 Sekunden
4.500008 Sekunden
4.510008 Sekunden
4.520009 Sekunden
4.530009 Sekunden
4.540009 Sekunden
4.550009 Sekunden
4.560009 Sekunden
4.570010 Sekunden
4.580010 Sekunden
4.590010 Sekunden
4.600010 Sekunden
4.610011 Sekunden
4.620011 Sekunden
4.630011 Sekunden
4.640011 Sekunden
4.650012 Sekunden
4.660012 Sekunden
4.670012 Sekunden
4.680012 Sekunden
4.690012 Sekunden
4.700013 Sekunden
4.710013 Sekunden
4.720013 Sekunden
4.730013 Sekunden
4.740014 Sekunden
4.750014 Sekunden
4.760014 Sekunden
4.770014 Sekunden
4.780015 Sekunden
4.790015 Sekunden
4.800015 Sekunden
4.810015 Sekunden
4.820015 Sekunden
4.830016 Sekunden
4.840016 Sekunden
4.850016 Sekunden
4.860016 Sekunden
4.870017 Sekunden
4.880017 Sekunden
4.890017 Sekunden
4.900017 Sekunden
4.910017 Sekunden
4.920018 Sekunden
4.930018 Sekunden
4.940018 Sekunden
4.950018 Sekunden
4.960019 Sekunden
4.970019 Sekunden
4.980019 Sekunden
4.990019 Sekunden
5.000020 Sekunden
5.010020 Sekunden
5.020020 Sekunden
5.030020 Sekunden
5.040020 Sekunden
5.050021 Sekunden
5.060021 Sekunden
5.070021 Sekunden
5.080021 Sekunden
5.090022 Sekunden
5.100022 Sekunden
5.110022 Sekunden
5.120022 Sekunden
5.130023 Sekunden
5.140023 Sekunden
5.150023 Sekunden
5.160023 Sekunden
5.170023 Sekunden
5.180024 Sekunden
5.190024 Sekunden
5.200024 Sekunden
5.210024 Sekunden
5.220025 Sekunden
5.230025 Sekunden
5.240025 Sekunden
5.250025 Sekunden
5.260026 Sekunden
5.270026 Sekunden
5.280026 Sekunden
5.290026 Sekunden
5.300026 Sekunden
5.310027 Sekunden
5.320027 Sekunden
5.330027 Sekunden
5.340027 Sekunden
5.350028 Sekunden
5.360028 Sekunden
5.370028 Sekunden
5.380028 Sekunden
5.390028 Sekunden
5.400029 Sekunden
5.410029 Sekunden
5.420029 Sekunden
5.430029 Sekunden
5.440030 Sekunden
5.450030 Sekunden
5.460030 Sekunden
5.470030 Sekunden
5.480031 Sekunden
5.490031 Sekunden
5.500031 Sekunden
5.510031 Sekunden
5.520031 Sekunden
5.530032 Sekunden
5.540032 Sekunden
5.550032 Sekunden
5.560032 Sekunden
5.570033 Sekunden
5.580033 Sekunden
5.590033 Sekunden
5.600033 Sekunden
5.610034 Sekunden
5.620034 Sekunden
5.630034 Sekunden
5.640034 Sekunden
5.650034 Sekunden
5.660035 Sekunden
5.670035 Sekunden
5.680035 Sekunden
5.690035 Sekunden
5.700036 Sekunden
5.710036 Sekunden
5.720036 Sekunden
5.730036 Sekunden
5.740036 Sekunden
5.750037 Sekunden
5.760037 Sekunden
5.770037 Sekunden
5.780037 Sekunden
5.790038 Sekunden
5.800038 Sekunden
5.810038 Sekunden
5.820038 Sekunden
5.830039 Sekunden
5.840039 Sekunden
5.850039 Sekunden
5.860039 Sekunden
5.870039 Sekunden
5.880040 Sekunden
5.890040 Sekunden
5.900040 Sekunden
5.910040 Sekunden
5.920041 Sekunden
5.930041 Sekunden
5.940041 Sekunden
5.950041 Sekunden
5.960042 Sekunden
5.970042 Sekunden
5.980042 Sekunden
5.990042 Sekunden
6.000042 Sekunden
6.010043 Sekunden
6.020043 Sekunden
6.030043 Sekunden
6.040043 Sekunden
6.050044 Sekunden
6.060044 Sekunden
6.070044 Sekunden
6.080044 Sekunden
6.090044 Sekunden
6.100045 Sekunden
6.110045 Sekunden
6.120045 Sekunden
6.130045 Sekunden
6.140046 Sekunden
6.150046 Sekunden
6.160046 Sekunden
6.170046 Sekunden
Leider kann ich nur schlecht mit ganzen Zahlen rechnen, weil ich eine Funktion habe, in die ich dann die korrekten Zahlen einsetzen muss... außerdem werden so wie mein t auch die anderen Variablen, die meistens vom float typ sind, über den gesamten Ablauf Fehler produzieren, die das ganze Ergebnis verfälschen..
Bin für alle Antworten und hilfreiche Tipps dankbar!
 
Zuletzt bearbeitet:
und wieso kannst du nicht mit ganzen Zahlen rechnen ?

Einfach die ganze Zahl Durch 100 und schon stimmt es ja ... ( x : 100 ) fertig aus Ende
 
Ich würde trotzdem mit unsigned int lösen.
Und bei der Verwendung rechnest du dann einfach mit "t * 0.01" in float um
 
Zuletzt bearbeitet:
Float variabeln sind je nach Bereich unterschiedlich genau (deshalb Floating Point Variabel) und relativ ungenau. Für solche Dinge würde ich double verwenden (ist deutlich präziser), oder wie schon erwähnt (unsigned) int und dann dividieren.
 
sushy schrieb:
Und bei der Verwendung rechnest du dann einfach mit "t * 0.01" in float um

Bie "t*0.01" werden dann wohl auch Sachen wie "0.8200000000000001" oder "0.8199999999999" raus kommen :).
 
Zuletzt bearbeitet:
Das Problem kommt daher, dass 0,01 nicht exakt als float bzw. double darstellbar ist (ja, auch doubles zu nutzen bringt hier nichts). Ein weiterer Punkt, wieso man von sukzessiver Addition kleiner Zahlen auf floats/doubles absehen sollte ist der Exponentenangleich. Irgendwann kommt man an einen Punkt, an dem +0,01 einfach keinerlei Auswirkung mehr hat, da 0,01 nicht mehr mit Expontent der großen Zahl darstellbar ist.
 
Mit %.2f kannst du einfach die hinteren Kommastellen abschneiden.

Also so:
printf(datei,"%.2f Sekunden\n",t);

Die zwei steht hierbei für die Anzahl der Kommastellen hinter dem Punkt.
Und zusätzlich natürlich double verwenden.

Sieht dann so aus für double:
printf(datei,"%.2lf Sekunden\n",t);
 
Deamp schrieb:
Bie "t*0.01" werden dann wohl auch Sachen wie "0.8200000000000001" oder "0.8199999999999" raus kommen :).
stimmt, aber der Fehler entsteht nur einmal bei der Umrechnung, es wird nicht tausende mal der Fehler erstellt und addiert. Von daher trotzdem wesentlich genauer.
 
Danke für die viele Hilfe!!
Ich dachte mir schon, dass int besser zu händeln ist :D
Müsste ich mich nochmal ranwagen, hab das bislang auch nur in C gemacht, nachher solls in Java geschrieben werden, was ich allerdings noch nicht wirklich drauf habe, da wirds ja dann ähnliche Probleme geben..
aaaaber: Double hat in der tat einiges genützt... konnte jetzt alles durchlaufen lassen und habe zum Ende die Zahl:
657.390000 Sekunden was tip top ist..
Ich werde jetzt die anderen Variablen auch mal ändern und gucken, ob meine Approximierte Darstellung dann gleiche Werte liefert
 
Mit double zögerst du das Problem nur ein wenig heraus.
Weder 0.1 noch 0.01 lassen sich in float oder double darstellen.
64bit reichen hierfür nicht aus:
http://www.binaryconvert.com/result_double.html?decimal=048046048049
Sowas macht man mit ints. Wenns dann als float dargestellt werden soll kannst du es im Moment der Darstellung ja umwandeln.
Dein float/double Ansatz hat neben den bereits genannten noch einen anderen ganz großen Nachteil: Der Fehler wächst mit der Zeit immer weiter.
 
Fischy33 schrieb:
nachher solls in Java geschrieben werden, [...] da wirds ja dann ähnliche Probleme geben..
Wenn du float und double benutzt, ja. Wenn du stattdessen BigDecimal benutzt, nein. Spar dir den Krampf in C und machs gleich richtig, wenn du es doch eh in Java brauchst. Syntaktisch ist das doch fast identisch.
 
bei allen gleitkommatypen ist folgendes der fall:

Code:
constexpr float value = 99.f;

float temp = value;

const bool test1 = ( temp == value );

temp = temp / 10.f;
temp = temp * 10.f;

const bool test2 = ( temp == value );

rauskommen wird, dass test2 false ist, obwohl test1 true ist, was unerwünscht ist. dies ist aber nicht weiter schlimm, insofern du ein epsilon benutzt, was um eine größenordnung kleiner ist als die gewünschte genauigkeit und die ganze arithmetik die mantisse deines gleitkommatypen nicht überstrapaziert, also:

Code:
constexpr float epsilon = 0.1f; // gewünscht wird eine genauigkeit auf einen eintel, drum reicht hier ein eps von einem zehntel.
/*
 den kram wie gehabt
*/
const bool test2 = ( fabs( temp - value ) < epsilon );

allgemein sollte man einen "==" vergleich bei gleitkommatypen meiden, weil das thema einfach ein mienenfeld ist.

in deinem fall rechnest du ja in 10ms schritten. drum ja, nimm lieber einen typen für ganze zahlen ohne vorzeichen. den kannst du bei der ausgabe immer noch duch 1000 teilen, um auf sekunden zu kommen.

Code:
float toSeconds( const std::uint32_t ms )
{
   // bedenke, dass der float-typ nur 23 bits für die mantisse übrig hat, wobei ms mit 32 bits daherkommt. ggf. den float gegen double ersetzen, je nachdem wie lange deine while-schleife läuft.
   return static_cast<float>( ms ) / 1000.f;
}

foo( ... )
{
   std::uint32_t elapsed = 0u; // in ms

   while( x < 0 )
   {
      ...
      elapsed += 10u;
      ...
      printf( datei, "%f Sekunden\n", toSeconds( elapsed ) );
      ...
   }
}
 
Zuletzt bearbeitet:

Ähnliche Themen

Zurück
Oben