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.
Hallo Rufus, Serial.println((uint32_t)test,HEX); Sollte aber passen, float hat: 1 Signed-Bit 8 Exponenten-Bits 23 Fraction Bits Grüße Seppel
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 Macel, hast Du einen anderen Vorschlag wie ich es auf der seriellen Schnittselle ausgeben kann? Vielen Dank, Seppel
P.S. Wenn man dem Tool glauben mag: https://www.h-schmidt.net/FloatConverter/IEEE754.html Dann ist: 1.024E13 0x551502f9 Also ich hänge irgendwie fest,... . Grüße Seppel
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
Die Klammern gingen eben verloren. Richtig heißen muss es natürlich: Serial.println(*reinterpret_cast<uint32_t*>(&test), HEX);
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.
Hallo, aber warum es mit der selbst geschriebenen Funktion"myPow10" klappt und mit pow(x,10) nciht`? Grüße Seppel
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.
Nach jedem Schleifendurchlauf das Zwischenergebnis ausgeben.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.