mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Mikrocontroller: Division optimieren


Autor: new_gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen,

ich möchte im Mikrocontroller in der Programmiersprache Ansi C einen 
Filter implementieren. Eine Fließkommazahl wird dabei mit einem double- 
Wert multipliziert.
1/20 * data[i] ....

(data ist ein Array vom Typ double)

Wie kann man den Faktor 1/20=0.05 optimiert mit Schiebeoperatoren in 
Ansi C implementieren?

Für jeden Vorschlag bin ich sehr dankbar.

Bye

Autor: Christian H. (netzwanze) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin mir jetzt nicht sicher.
Aber es könnte sein, dass 1/20 als integer berechnet wird, was dann 0 
ergibt.
Es könnte sein, dass man besser 1.0/20 schreiben sollte.

Kannst Du nicht auf Festkommarechnungen umsteigen?
Also statt 0.05 den Wert 5 verwenden und Data (also integer) mit 100 
multiplizieren?

Nur so 'ne idee.

Autor: vlad (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was soll das bringen?
doubles kann man nicht schiften.
wenn dein array sowiso doubles enthält kannst dus auch direkt mit einem 
double multiplizieren.

Autor: new_gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die schnellen Antworten.
Nach eurer Erfahrung kann man die nicht weiter optimieren?
Hab gedacht man kann dies mit Schiebeoperatoren wesentlich optimieren.

Autor: vlad (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hatte da mal ein perl-script geschrieben, was sowas berechnet
Das spuck fü .0.2 folgende Liste aus:
die abweichung vom 0.02 nimmt immer weiter ab.

( x * 1 ) >> 5 = x * 0.03125
( x * 1 ) >> 6 = x * 0.015625
( x * 3 ) >> 7 = x * 0.0234375
( x * 5 ) >> 8 = x * 0.01953125
( x * 11 ) >> 9 = x * 0.021484375
( x * 21 ) >> 10 = x * 0.0205078125
( x * 41 ) >> 11 = x * 0.02001953125
( x * 81 ) >> 12 = x * 0.019775390625
( x * 163 ) >> 13 = x * 0.0198974609375
( x * 327 ) >> 14 = x * 0.01995849609375
( x * 655 ) >> 15 = x * 0.019989013671875
( x * 1311 ) >> 16 = x * 0.0200042724609375
( x * 2621 ) >> 17 = x * 0.0199966430664063
( x * 5243 ) >> 18 = x * 0.0200004577636719
( x * 10485 ) >> 19 = x * 0.0199985504150391
( x * 20971 ) >> 20 = x * 0.0199995040893555
( x * 41943 ) >> 21 = x * 0.0199999809265137
( x * 83887 ) >> 22 = x * 0.0200002193450928
( x * 167773 ) >> 23 = x * 0.0200001001358032
( x * 335545 ) >> 24 = x * 0.0200000405311584
( x * 671089 ) >> 25 = x * 0.0200000107288361
( x * 1342177 ) >> 26 = x * 0.0199999958276749
( x * 2684355 ) >> 27 = x * 0.0200000032782555
( x * 5368709 ) >> 28 = x * 0.0199999995529652
( x * 10737419 ) >> 29 = x * 0.0200000014156103
( x * 21474837 ) >> 30 = x * 0.0200000004842877
( x * 42949673 ) >> 31 = x * 0.0200000000186265

du musst natürlich auf deinen Wertebereich achten, damit bei der 
Multiplikation das x nicht überläuft.

Autor: vlad (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
optimieren kannst du das nur, wenn du die doubles wegbekommst und durch 
fix-points ersetzt.
oder mach wenigstesn floats aus den doubles (wenn das auf deinem System 
nicht sowiso identisch ist)

Was hast du denn für einen µC? Wenn der eine FPU hat brauchst du dir 
natürlich gar keine gedanken machen, dann fürd ich nur auf

Autor: vlad (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Kannst Du nicht auf Festkommarechnungen umsteigen?
>Also statt 0.05 den Wert 5 verwenden und Data (also integer) mit 100
>multiplizieren?


Naja ein skalierungsfaktor von 100 ist auch nicht wirklich ideal.
besser wär eine Potenz von 2

wenn du zwei werte mit skalierungsfaktor 100 multiplizierstz ist die 
resultierende skalierung 200, das heißt du musst durch 10000, dh du 
musst durch 100 teilen, wenn du die ureprüngliche wieder haben willst.


wenn du mit zB 128 skalierst, musst du nach der multiplikation durch 128 
teilen, was nur ein bitshift ist

Autor: vlad (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>wenn du zwei werte mit skalierungsfaktor 100 multiplizierstz ist die
>resultierende skalierung 200, das heißt du musst durch 10000, dh du
>musst durch 100 teilen, wenn du die ureprüngliche wieder haben willst.

quatsch, da ist ein satzteil zu viel:
so sollte es aussehen:
>wenn du zwei werte mit skalierungsfaktor 100 multiplizierstz ist die
>resultierende skalierung 10000, dh du musst durch 100 teilen, wenn du die 
ureprüngliche wieder haben willst.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht sollte man über Festkommaarithmetik nachdenken.

Autor: new_gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für eure zahlreichen Beiträge. Bin jetzt irgendwie verwirrt.
Was soll ich nun tun?

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

Bewertung
0 lesenswert
nicht lesenswert
new_gast schrieb:
> Vielen Dank für eure zahlreichen Beiträge. Bin jetzt irgendwie verwirrt.
> Was soll ich nun tun?

Zuerst mal darüber nachdenken, wie du aus data einen int oder long 
machen kannst. Solange data double ist, ist es sinnlos über die Division 
von 1/20.0 nachzudenken.

Vorgehensweise:
Den möglichen Wertebereich festlegen und auch welche Operationen mit 
diesen Werten gemacht werden. Mit diesem Wissen kann man dann hergehen 
und Skalierfaktoren festlegen um die kompletten Berechnungen von double 
in den Ganzzahlbereich zu verlagern.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da wir nicht wissen, um welchen µC es sich handelt, tippe ich darauf, 
daß die double-Variable intern vom Compiler als float behandelt wird.

Zweitens sehe ich garkeine Notwendigkeit, irgendeine Optimierung 
durchzuführen. Probleme bei der Verarbeitungsgeschwindigkeit sind nicht 
erwähnt.

Soll der Compiler doch optimieren, wo er kann.

Autor: new_gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist ein 16Bit Mikrocontroller Typ:XC164

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zumindest macht jeder halbwegs intelligente Compiler aus
1.0/20*x ein 0.05*x; notfalls kann man es von Hand so
hinschreiben.
Damit hat man schon mal keine Division, sondern eine
Multiplikation.

Vielleicht kann man das Programm auch so umbauen, daß es
nicht gerade 20 sein muß?
Wenn es nur eine Skalierung ist, die etwas in die richtige
Größenordnung schiebt und man auch z.B. mit 16 oder 32 leben
kann, kann man 1/16.0*x oder 1/32.0*x auch durch ein einfaches
Shiften direkt im Exponentialteil der Gleitkommazahl
ersetzen.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Das ist ein 16Bit Mikrocontroller Typ:XC164

Und warum soll von Hand optimiert werden?

Autor: vlad (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Zweitens sehe ich garkeine Notwendigkeit, irgendeine Optimierung
>durchzuführen. Probleme bei der Verarbeitungsgeschwindigkeit sind nicht
>erwähnt.

Wenn er so ne kleine division mit ner Konstante wegbekommen will, gehe 
ich mal davon aus, dass er Laufzeitprobleme hat.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> gehe ich mal davon aus, dass er Laufzeitprobleme hat.

Ich glaube nur noch, was ich sehe! :-)

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.