Mikrocontroller: Division optimieren

Gast #1311656
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
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.
Gast
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
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
>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
>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.
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
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.
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
>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

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.