Forum: Mikrocontroller und Digitale Elektronik Mikrocontroller: Division optimieren


von new_gast (Gast)


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

von Christian H. (netzwanze) Benutzerseite


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.

von vlad (Gast)


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.

von new_gast (Gast)


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.

von vlad (Gast)


Angehängte Dateien:

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.

von vlad (Gast)


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

von vlad (Gast)


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

von vlad (Gast)


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.

von Falk B. (falk)


Lesenswert?

Vielleicht sollte man über Festkommaarithmetik nachdenken.

von new_gast (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


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.

von Gast (Gast)


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.

von new_gast (Gast)


Lesenswert?

Das ist ein 16Bit Mikrocontroller Typ:XC164

von Klaus W. (mfgkw)


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.

von Gast (Gast)


Lesenswert?

>Das ist ein 16Bit Mikrocontroller Typ:XC164

Und warum soll von Hand optimiert werden?

von vlad (Gast)


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.

von Gast (Gast)


Lesenswert?

> gehe ich mal davon aus, dass er Laufzeitprobleme hat.

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

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
Noch kein Account? Hier anmelden.