www.mikrocontroller.net

Forum: Compiler & IDEs Paramterübergabe pow


Autor: TechInfo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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).
long Faktoren[] = { 1, 10, 100, 1000, 10000, 100000, 10000000 };

double Round(double Zahl, int Stellen)
{
  if( Stellen >= sizeof( Faktoren ) / sizeof( *Faktoren ) )
    Stellen = sizeof( Faktoren ) / sizeof( *Faktoren ) - 1;
  if( Stellen < 0 )
    Stellen = 0;

  long i = Faktoren[Stellen];

  ...


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.



Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: TechInfo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: TechInfo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, verstanden, vielen Dank.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.