Hallo,
ich ärgere mich seit einigen Tagen mot pow() herum:
Führe ich das mit 20.0^5.0 aus:
double test = pow((float)20.0,(float)10.0)
Dann ist das Ergebnis korrekt:
0x0030D400
3200000.00
Führe ich das mit 20.0^10.0 aus:
double test = pow((float)20.0,(float)10.0)
Dann ist das Ergebnis Falsch:
FFFFFFFF
ovf
Eigentlich ist der float Wertebereich(double ist bei den 8Bit AVR's
gleich) bis 3.403E+38, 20^10 (1.024E+13 ) passt also locker rein.
Was geht da ab, was mache ich falsch?
Vielen Dank,
Grüße
Seppel
Seppel schrieb:> Dann ist das Ergebnis korrekt:>> 0x0030D400
Das ist kein Float. Wie erzeugst Du dieses "Ergebnis"?
In Deiner Variablen "test" steht das so sicher nicht drin.
Seppel schrieb:> Serial.println((uint32_t)test,HEX);
Das geht schief. 20^10 ist 10.240.000.000.000. Das ist bedeutend größer
als der größte mit uint32_t repräsentierbare Wert.
Viele Grüße,
Marcel
Hallo Seppel,
ich glaube, da liegt ein Missverständnis vor.
Mit "(uint32_t) test" wird der Floating-Point-Wert in einen Integer
umgewandelt und nicht nur als Integer interpretiert.
Entsprechend dem von dir verlinkten Tool möchtest du folgendes
erreichen:
Serial.println(*reinterpret_cast<uint32_t*>&test, HEX);
Viele Grüße,
Marcel
Hallo,
hab's mit einem pointer gelöst, nicht schön(ja richtig böse),... aber
geht auch.
----------------------------------------------------------------------
Ich hab folgendes probiert:
float mytest2 = 1.024E13;
uint32_t* oh = (uint32_t*)&mytest2;
Serial.println("Test2");
Serial.println((uint32_t)*oh,HEX);
Das Ergebnis ist:
Test2
551502F9
-------------------------------------
Also, wie zu erwarten war, float (IEEE754) kann 1.024E13 darstellen, das
ist schon mal gut dass das klappt.
----------------------------------------------------------------------
Da ich nur ganzzahlige Exponenten brauche hab ich mir eine Funktion
selbst geschrieben:
double myPow (double base, uint8_t exponent)
{
uint8_t iter = (exponent-1U);
double result = base;
for ( ; (iter>0) ; (iter=iter-1) )
{
result = (result * base);
}
return result;
}
-------------------------------------
Geht immer noch nicht. Wahrscheinlich liegt das daran dass mit
steigendem Iterator eine große mit einer kleinen Zahl multipliziert wird
und dann die Ungenauigkeiten ein sinnvolles Ergebnis verhindern, sicher
bin ich aber nicht.
----------------------------------------------------------------------
Hat jemand eine Idee wie ich das läsen kann?
Vielen Dank,
Grüße
Seppel
Seppel schrieb:> Hat jemand eine Idee wie ich das läsen kann?
was ist das genau Problem? Willst du einen Rechnen per Seriell
programmieren oder hat da ganze auch einen Zweck?
Es mag ja Anwendungen geben, wo man so große Zahlen fast ohne
Genauigkeit braucht, aber mir ist bis jetzt keine untergekommen.
P.S.
Und jetzt kommt der Knaller:
double myPow10 (double base)
{
return (
(((base*base)*(base*base))*((base*base)*(base*base)*(base*base)))
);
}
Es geht,....
Kann mir jemand erklären was da schief läuft wenn man das mit einer for
Loop macht?
Vielen Dank,
Grüße
Seppel
Seppel schrieb:> Da ich nur ganzzahlige Exponenten brauche hab ich mir eine Funktion> selbst geschrieben:
Warum?
Soll die schneller und/oder genauer sein?
Meist weiß der Compiler selber besser, wann er pow ersetzen kann.
(macht er, wenn z.B. der Exponent konstant und klein ist)
Hallo Dirk,
Mit der von mir geschriebenen "Hard Coded" 20.0^10 funktioniert es, mit
pow nicht. Ich weiß auch nicht was Du mit "Meist weiß der Compiler
selber besser, wann er pow ersetzen kann." meinst.
Und nein, in der Applikation sind die Exponenten nicht konstant, nur
ganzzahlig.
Grüße
Seppel
Seppel schrieb:> hab's mit einem pointer gelöst, nicht schön(ja richtig böse),... aber> geht auch.
Das nennt sich Pointer Type Punning und ist undefiniertes Verhalten,
weil es zugleich auch Pointer Aliasing ist. Kann gehen, kann auch
jederzeit nicht gehen. Type Punning würde ich über eine Union machen.
Seppel schrieb:> ber warum es mit der selbst geschriebenen Funktion"myPow10" klappt und> mit pow(x,10) nciht`?
Da müsstest Du mal genau posten (komplettes Beispiel) wie Du das
überprüfst.