mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Aufrundfunktion?


Autor: Reinhold (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich brauche folgende "Umrechnung":

0 -> 0
1-8 -> 8
9-16 -> 16
17-24 -> 24
25-32 -> 32

Wie würdet ihr das am effektivsten in C implementieren?

Gruß
Reinhold

Autor: Dussel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine einfache if-else-Konstruktion ist sicher nicht ineffektiv. Wenn der 
Compiler einigermaßen gut ist, sind das wenige Takte und relativ wenig 
Code. Etwas Effektiveres fällt mir spontan nicht ein.
Da die 'Bereichsgrenzen' Vielfache von acht sind, könnte man vielleicht 
nochwas über das dritte Bit machen, aber selbst wenn das geht, wird das 
nicht viel kürzer und schneller werden als mit if.

Autor: Simon Budig (nomis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Reinhold schrieb:
> ich brauche folgende "Umrechnung":
>
> 0 -> 0
> 1-8 -> 8
> 9-16 -> 16
> 17-24 -> 24
> 25-32 -> 32
>
> Wie würdet ihr das am effektivsten in C implementieren?
((x + 7) / 8) * 8;

Viele Grüße,
        Simon

Autor: raketenfred (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mit dem vielfachen von 8 kann man wirklich was machen:

die zahl in 2 teile splitten:

1. Teil: bit(0,1,2)
2. Teil: bit(3,4,5,6,...)
und dann nur noch ausgabe:
return (2.teil+1.teil!=0)+"000"

die letzten 3 stellen sind 0 wegen runden und der vordere teil ggf. +1 
wenn wir kein vielfaches von 8 haben

Autor: Abakus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde den Compiler gar nicht erst "auf dumme Gedanken bringen", eine 
Division und einen Multiplikation zu verwenden. ;-)

Dem kürzestmöglichen Maschinencode dürfte folgendes C-Konstrukt 
nahekommen:

int  In, Out;

Out = ((In+7)<<3)>>3;

Autor: raketenfred (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon Budig schrieb:
> ((x + 7) / 8) * 8;

float oder int?

float: return x+7;

int: x+7 und dann die letzten 3 bits auf 000 setzten

Autor: Simon Budig (nomis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abakus schrieb:
> Ich würde den Compiler gar nicht erst "auf dumme Gedanken bringen", eine
> Division und einen Multiplikation zu verwenden. ;-)
>
> Dem kürzestmöglichen Maschinencode dürfte folgendes C-Konstrukt
> nahekommen:
>
> int  In, Out;
>
> Out = ((In+7)<<3)>>3;

Und wuppdich haben wir den Beweis, warum es manchmal doch besser ist, 
die Division/Multiplikation einfach hinzuschreiben...   :-)

Viele Grüße,
        Simon

Autor: Anja (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Abakus schrieb:
> Dem kürzestmöglichen Maschinencode dürfte folgendes C-Konstrukt
> nahekommen:
>
> int  In, Out;
>
> Out = ((In+7)<<3)>>3;

enthält leider gleich mehrere mögliche Problemfälle:
1. Falls In > 8185 (0x1FF9) oder < -8192 (0xE000) ist ergibt sich ein 
Überlauf und damit eine ungewollte Änderung der Bits.

2. in Ansi-C ist rechts-schieben von negativen Zahlen (Datentyp int) 
undefiniert.
Wenn ich also (-1) >> 1 schreibe erhalte ich je nach Compiler als 
Ergebnis entweder -1 (rechts shift mit Vorzeichenerweiterung) oder 32767 
(rechts shift ohne Vorzeichenerweiterung).


ich würde schreiben:
Y = (X+7) & 0xFFF8;

Die Und-Maske ist natürlich an den Datentyp anzupassen. Ich gehe mal von 
uint16_t aus. Der TE muß dann nur noch überlegen was mit Überläufen für 
X >= 65529  (>= 0xFFF9) passieren soll.

Gruß Anja

Autor: Reinhold (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

vielen Dank für die Inspirationen!
Ich habe nun diese Variante benutzt:

y = (x + 7) & 0xF8;

Ich benutze als Datentyp uint8_t (hatte ich vergessen zu erwähnen). Der 
Spezialfall für Werte > 248 ist unkritisch, so groß wird der Wert nie.

Liebe Grüße
Reinhold

Autor: Anja (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Reinhold schrieb:
> Wie würdet ihr das am effektivsten in C implementieren?

Reinhold schrieb:
> y = (x + 7) & 0xF8;

Beim GCC-Compiler und uint8_t kann es sinnvoll sein für den Zwischenwert
(x + 7) eine Registervariable vom Typ uint8_t zu spendieren um den 
compiler zu überreden alles als uint8_t zu rechnen (und nicht als 
uint16_t).
also so:

register uint8_t z;

z = x + 7;
y = z & 0xF8;

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.