Floats & Doubles in- und dekrementieren

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Regenduft
Beiträge: 574
Registriert: 25.03.2008 15:07
Wohnort: THE LÄÄÄND!

Floats & Doubles in- und dekrementieren

Beitrag von Regenduft »

Mit den folgenden Prozeduren kann man den Wert einer Float- oder Doublevariable auf den nächstmöglichen Wert inkrementieren oder dekrementieren. Ich habe mal zwei Varianten gepostet: Bei der ersten werden die veränderten Werte rückgegeben und bei der zweiten werden die Variablen direkt manipuliert.

1. Variante (mit Rückgabewerten):

Code: Alles auswählen

Procedure.f IncF(Value.f)
  Protected *l.Long = @Value
  
  If *l\l & $7F800000 <> $7F800000 Or *l\l & $7FFFFF = 0 ; IsNAN(Value)=0 <- Geschwindigkeitsoptimierung
    
    ; positive Float inkrementieren
    If Value > 0
      If *l\l < $7F800000 ; IsInfinity(Value)=0 <- Geschwindigkeitsoptimierung
        *l\l + 1
      EndIf
    
    ; negative Float inkrementieren
    ElseIf Value < 0
      *l\l - 1
    
    ; Null-Float inkrementieren
    Else
      *l\l = 1
    EndIf
    
  EndIf
  
  ProcedureReturn Value
EndProcedure


Procedure.d IncD(Value.d)
  Protected *q.Quad = @Value
  
  If *q\q & $7FF0000000000000 <> $7FF0000000000000 Or *q\q & $000FFFFFFFFFFFFF = 0 ; IsNAN(Value)=0 <- Geschwindigkeitsoptimierung
    
    ; positive Float inkrementieren
    If Value > 0
      If *q\q < $7FF0000000000000 ; IsInfinity(Value)=0  <- Geschwindigkeitsoptimierung
        *q\q + 1
      EndIf
    
    ; negative Float inkrementieren
    ElseIf Value < 0
      *q\q - 1
    
    ; Null-Float inkrementieren
    Else
      *q\q = 1
    EndIf
    
  EndIf

  ProcedureReturn Value
EndProcedure


Procedure.f DecF(Value.f)
  Protected *l.Long = @Value
  
  If *l\l & $7F800000 <> $7F800000 Or *l\l & $7FFFFF = 0 ; IsNAN(Value)=0 <- Geschwindigkeitsoptimierung
    
    ; positive Float dekrementieren
    If Value > 0
      *l\l - 1
    
    ; negative Float dekrementieren
    ElseIf Value < 0
      If *l\l < $FF800000 ; Value > -Infinity() <- Geschwindigkeitsoptimierung
        *l\l + 1
      EndIf
    
    ; Null-Float dekrementieren
    Else
      *l\l = $80000001 ; <- kleinstmöglicher negativer Wert vor -0
    EndIf
    
  EndIf
  
  ProcedureReturn Value
EndProcedure


Procedure.d DecD(Value.d)
  Protected *q.Quad = @Value
  
  If *q\q & $7FF0000000000000 <> $7FF0000000000000 Or *q\q & $000FFFFFFFFFFFFF = 0 ; IsNAN(Value)=0 <- Geschwindigkeitsoptimierung
    
    ; positive Float dekrementieren
    If Value > 0
      *q\q - 1
    
    ; negative Float dekrementieren
    ElseIf Value < 0
      If *q\q < $FFF0000000000000 ; Value > -Infinity() <- Geschwindigkeitsoptimierung
        *q\q + 1
      EndIf
    
    ; Null-Float dekrementieren
    Else
      *q\q = $8000000000000001 ; <- kleinstmöglicher negativer Wert vor -0
    EndIf
    
  EndIf
  
  ProcedureReturn Value
EndProcedure
2. Variante (direkte Manipulation):

Code: Alles auswählen

Procedure IncF(*Value.Float)
  Protected *l.Long = *Value
  
  If *l\l & $7F800000 <> $7F800000 Or *l\l & $7FFFFF = 0 ; IsNAN(Value)=0 <- Geschwindigkeitsoptimierung
    
    ; positive Float inkrementieren
    If *Value\f > 0
      If *l\l < $7F800000 ; IsInfinity(Value)=0 <- Geschwindigkeitsoptimierung
        *l\l + 1
      EndIf
    
    ; negative Float inkrementieren
    ElseIf *Value\f < 0
      *l\l - 1
    
    ; Null-Float inkrementieren
    Else
      *l\l = 1
    EndIf
    
  EndIf
  
EndProcedure


Procedure IncD(*Value.Double)
  Protected *q.Quad = *Value
  
  If *q\q & $7FF0000000000000 <> $7FF0000000000000 Or *q\q & $000FFFFFFFFFFFFF = 0 ; IsNAN(Value)=0 <- Geschwindigkeitsoptimierung
    
    ; positive Float inkrementieren
    If *Value\d > 0
      If *q\q < $7FF0000000000000 ; IsInfinity(Value)=0  <- Geschwindigkeitsoptimierung
        *q\q + 1
      EndIf
    
    ; negative Float inkrementieren
    ElseIf *Value\d < 0
      *q\q - 1
    
    ; Null-Float inkrementieren
    Else
      *q\q = 1
    EndIf
    
  EndIf

EndProcedure


Procedure DecF(*Value.Float)
  Protected *l.Long = *Value
  
  If *l\l & $7F800000 <> $7F800000 Or *l\l & $7FFFFF = 0 ; IsNAN(Value)=0 <- Geschwindigkeitsoptimierung
    
    ; positive Float dekrementieren
    If *Value\f > 0
      *l\l - 1
    
    ; negative Float dekrementieren
    ElseIf *Value\f < 0
      If *l\l < $FF800000 ; Value > -Infinity() <- Geschwindigkeitsoptimierung
        *l\l + 1
      EndIf
    
    ; Null-Float dekrementieren
    Else
      *l\l = $80000001 ; <- kleinstmöglicher negativer Wert vor -0
    EndIf
    
  EndIf
  
EndProcedure


Procedure DecD(*Value.Double)
  Protected *q.Quad = *Value
  
  If *q\q & $7FF0000000000000 <> $7FF0000000000000 Or *q\q & $000FFFFFFFFFFFFF = 0 ; IsNAN(Value)=0 <- Geschwindigkeitsoptimierung
    
    ; positive Float dekrementieren
    If *Value\d > 0
      *q\q - 1
    
    ; negative Float dekrementieren
    ElseIf *Value\d < 0
      If *q\q < $FFF0000000000000 ; Value > -Infinity() <- Geschwindigkeitsoptimierung
        *q\q + 1
      EndIf
    
    ; Null-Float dekrementieren
    Else
      *q\q = $8000000000000001 ; <- kleinstmöglicher negativer Wert vor -0
    EndIf
    
  EndIf
  
EndProcedure
Hab' das für ein Projekt benötigt und dachte andere könnten es vielleicht nützlich finden. Ich hoffe mal, dass ich (a) keine Denk- oder Schreibfehler begangen habe und (b) der Code dieses Forums würdig ist (im Zweifelsfall plädiere ich auf "einfach cool"). <)
PureBasic 5.73 LTE x86/x64 | Windows 7 (x64)