Habe eine Rundungsfunktion, die als Parameter die zu rundende Zahl erhält sowie Anzahl der Stellen, auf die gerundet werden soll. Z.B. Round (1.123, 2.0) ergibt 1.12 Ausschnitt: double Round(double Zahl, double Stellen) { int i=0; i=pow(10, Stellen); [...] Das funktioniert für 2 Stellen auch wunderbar. Wenn ich aber "3" für Stellen eingebe, wird i zu 0 anstatt 1000. Bei allen Werten größer als "3" wird i zu 1. Die pow-Funktion scheint in Ordnung zu sein, denn mit Konstanten funktioniert sie. Es scheint also an der Parameterübergabe zu liegen. Hat jemand eine Idee?
Das sollte normalerweise funktionieren, solange der Wertebereich von int nicht überschritten wird. Schau mal nach, wie groß die ints auf deinem Zielprozessor sind. Bei 16 Bit sollte 10 hoch 3 noch darstellbar sein, 10 hoch 4 aber nicht mehr. Hast du einen AVR und beim Compiler -mint8 eingestellt? Dann ist schon bei 10 hoch 2 Schluss. Was du zusätzlich beachten solltest: Je nach Implementation von pow() kann es passieren, dass bspw. 10 hoch 3 nicht 1000, sondern 999.9999 ergibt. Die Umwandlung nach int ergibt dann 999, was sicher nicht deinen Vorstellungen entspricht. Aus den genannten Gründen würde ich das i als double deklarieren. Aber auch dann hast du natürlich immer noch das Problem, dass das gerundete Ergebnis (z. B. 1.234) intern nicht immer exakt darstellbar ist und durchaus auch 1.233999 oder 1.234001 sein kann.
yalu wrote: > Aus den genannten Gründen würde ich das i als double deklarieren. Aber > auch dann hast du natürlich immer noch das Problem, dass das gerundete > Ergebnis (z. B. 1.234) intern nicht immer exakt darstellbar ist und > durchaus auch 1.233999 oder 1.234001 sein kann. Um das weiterzuführen: Das ist aber kein Problem. Da macht man eine Rundungskorrektur dran und fertig: i = (int)( pow(10, Stellen) + 0.5); Aber ganz was anderes in diesem Zusammenhang. pow() ist eine teure Funktion! Und jetzt stell ich mal die Frage, was denn übliche Werte für Stellen sein könnten. Ich wage mal die Behauptung, dass ausser den Werten 0, 1, 2, 3, 4, 5, 6 praktisch keine anderen Werte vorkommen werden. Ergo würde ich das ganze komplett ohne pow machen und stattdessen eine Tabelle nehmen (und Stellen als int ausführen. Du kannst keine 2.5 Nachkommastellen haben. unsigned int wäre noch besser, aus praktischen Gründen belasse ich es aber bei int).
1 | long Faktoren[] = { 1, 10, 100, 1000, 10000, 100000, 10000000 }; |
2 | |
3 | double Round(double Zahl, int Stellen) |
4 | {
|
5 | if( Stellen >= sizeof( Faktoren ) / sizeof( *Faktoren ) ) |
6 | Stellen = sizeof( Faktoren ) / sizeof( *Faktoren ) - 1; |
7 | if( Stellen < 0 ) |
8 | Stellen = 0; |
9 | |
10 | long i = Faktoren[Stellen]; |
11 | |
12 | ...
|
Das dürfte * um einiges schneller sein * wenn pow() sonst nirgends im Pgm gebraucht wird auch um einiges platzsparender sein. Allerdings: Es löst nicht das ursprüngliche Problem, zu dem ich auch keine Idee habe was da schiefgelaufen sein könnte.
Karl heinz Buchegger wrote: > Allerdings: > Es löst nicht das ursprüngliche Problem, zu dem ich auch keine > Idee habe was da schiefgelaufen sein könnte. Ach das war ja wieder TechInfo mit seinem Xilinx (oder wie das heist) System bei dem der Compiler anscheinend hinten und vorne Probleme mit Floating Point hat. Was sagt eigentlich der Compiler Hersteller zu deiner mitlerweile nicht unbedeutenden Latte von Fehlern?
@yalu Mit i als double habe ich genau das gleiche Problem. @Karl-Heinz Kannst du mir deinen Code mal genauer erklären? Größe von Faktoren durch Größe vom Inhalt von Faktoren? Häh? ;) Ich bin mir nicht sicher ob diese Probleme vom Compiler her rühren. Die treten ja anscheinend immer dann auf, wenn Funktionen mit viel Stackbedarf verwendet werden (schätze mal, pow gehört dazu). Andererseits gibt es auch im zugehörigen GNU-Debugger Probleme, manche Variablen-Inhalte werden falsch angezeigt obwohl intern alles richtig ist... Der Xilinx-Distributor hat übrigens keine Ahnung und empfiehlt: "Neue Version bei uns kaufen!" ;) Na vielen Dank...
TechInfo wrote:
> Größe von Faktoren durch Größe vom Inhalt von Faktoren? Häh? ;)
Das ist die übliche Art und Weise wie man eine Arraygröße
feststellen kann ohne die Zahl selbst in den Code mit
aufzunehmen:
Größe_vom_kompletten_Array / Größe_des_ersten_Array_Elementes
T Feld[] = { .... }
Größe des kompletten Arrays in Bytes
sizeof( Feld )
Größe des ersten Array Elements in Bytes
sizeof( *Feld ) oder
sizeof( Feld[0] ) oder
sizeof( T )
Die Anzahl der Elemente ist daher
sizeof( Feld ) / sizeof( *Feld )
Sieht wild aus, wird aber vom Compiler berechnet und kostet
daher nichts zur Laufzeit.
Vorteil:
Die fügst eine weitere Zahl zur Initialisierung dazu und um den
Rest kümmert sich der Compiler.
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.