Mikrocontroller: Division optimieren

Gast #1311656
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
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
Gast #1311665
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.
Angehängte Dateien:
Gast #1311671
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
Gast #1311702
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
Gast #1311706
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.
#1311751
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.
Gast #1311788
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.
#1311809
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.
Gast #1311873
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.

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