Arduino: double test = pow((float)20.0,(float)10.0) kein sinnvolles Ergebnis?

Gast #4842248
Lesenswert?

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
Gast #4842314
Lesenswert?

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
Gast #4842393
Lesenswert?

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
Gast #4842399
Lesenswert?

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.
Gast #4842411
Lesenswert?

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
Gast #4842497
Lesenswert?

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
Gast #4842529
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren