Ergebnis einer Rechenoperation auf den Wertebereich begrenzen

#1293452
Prozessoren mit Befehlssatzerweiterung für DSP oder Multimedia 
unterstützen manche Formen saturierter Arithmetik. Üblicherweise gibt es 
dann Include-Files für Pseudofunktionen, mit denen man dies nutzen kann.

Portabel ist das natürlich nicht.
Persönliche Seite #1293459
Das heisst Saturierung was sich übersetzen lässt mit Sättigung und 
ist keine Eigenschaft des Ergebnisses oder eines Wertes, sondern eines 
Operators.

Mansche Maschinen kennen Instruktionen für saturierte Operationen wie 
Addition, Subtraktion, Betrag, Shift. Oft dann in den 
Geschmacksrichtungen signed und unsigned.

Manche GCC-Versionen stellen Builtin-Funktionen dafür zur Verfügung, 
z.b. für ARM Neon.

Ansonsten muss man die "normale" Operation über einem weiteren 
Werteberech ausführen in dem kein Über/Unterlauf auftreten kann und dann 
per Vergleich bzw. Minimum/Maximum auf die gewünschten Bereich 
begrenzen.

Johann
#1293483
Johann L. schrieb:

> Ansonsten muss man die "normale" Operation über einem weiteren
> Werteberech ausführen in dem kein Über/Unterlauf auftreten kann und dann
> per Vergleich bzw. Minimum/Maximum auf die gewünschten Bereich
> begrenzen.

Wenn man eigene Funktionen schreiben muss, sollte man auch darüber 
nachdenken, ob es möglich ist vor der Operation schon vorherzusagen, ob 
das Ergebnis den Bereich verlassen wird.

Im obigen Beispiel ist das sehr leicht möglich


  uint8_t Foo=10
  if( Foo > 100 )
    Foo -= 100
  else
    Foo = 0;

Bei komplizierteren Ausdrücken, kann das natürlich entsprechend 
komplexer werden.
Persönliche Seite #1293507
Karl heinz Buchegger schrieb:
> Johann L. schrieb:
>
>> Ansonsten muss man die "normale" Operation über einem weiteren
>> Werteberech ausführen in dem kein Über/Unterlauf auftreten kann und dann
>> per Vergleich bzw. Minimum/Maximum auf die gewünschten Bereich
>> begrenzen.
>
> Wenn man eigene Funktionen schreiben muss, sollte man auch darüber
> nachdenken, ob es möglich ist vor der Operation schon vorherzusagen, ob
> das Ergebnis den Bereich verlassen wird.
>
> Im obigen Beispiel ist das sehr leicht möglich
>
>
>   uint8_t Foo=10
>   if( Foo > 100 )
>     Foo -= 100
>   else
>     Foo = 0;
>

Das tut es glaub nicht.
1
uint8_t a, b;
2
uint8_t ab = a+b;
3

4
if (ab < a)
5
  ab = 255;

und signed:
1
int8_t a, b;
2
int8_t ab = a+b;
3

4
if (b >= 0)
5
{
6
  if  (ab < a)
7
     ab = 127;
8
}
9
else
10
{
11
  if  (ab > a)
12
     ab = -128;
13
}
Gast #1293564
Danke für die Antworten!
Bis jetzt hab ich es auch immer so gelöst das ich eine variable mit 
größerem Wertebereich genommen hab und dann mit 2 if's begrenzt hab. 
Dachte nur vielleicht gibt es eine einfachere Platz/Zeitsparende 
Möglichkeit.
Persönliche Seite #1295253
Je nach Maschine/Compiler kann man zB das Carry-Flag dazu ausnutzen und 
muss nicht auf einen größeren Typen ausweichen.

Für AVR+GCC geht zum Beispiel
1
#include <stdint.h>
2

3
// unsigned saturated addition, 8 bit
4
static inline uint8_t usadd8 (uint8_t a, uint8_t b)
5
{
6
    asm  ("add %0, %1"  "\n\t"
7
          "brcc 0f"     "\n\t"
8
          "ldi %0, 255" "\n\t"
9
          "0:"
10
          : "+d" (a)
11
          : "r" (b));
12
          
13
    return a;
14
}
15

16
uint8_t add42 (uint8_t a, uint8_t b)
17
{
18
    return usadd8 (usadd8 (a, 42), b);
19
}

Der Code ist dann
1
add42:
2
  ldi r25,lo8(42)   ;  tmp46
3
  add r24, r25   ;  a, tmp46
4
  brcc 0f
5
  ldi r24, 255   ;  a
6
  0:
7
  add r24, r22   ;  a, b
8
  brcc 0f
9
  ldi r24, 255   ;  a
10
  0:
11
  ret

Johann

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.