Seite 1 von 2

Zahl immer negativ (-Abs ())

Verfasst: 06.04.2005 16:22
von pLuSmaN
Hi,

der Threadtitel ist evtl. etwas "ungünstig" gewählt, aber ich wollte da keinen ganzen Roman rein schreiben.

Nunja, also ich möchte sozusagen ohne Asm. eine Funktion schreiben, die einen Parameter (Pointer) immer negativ setzt. D.h., dass wenn die Variable bereits negativ ist, soll sie den Wert nicht ändern. Ist sie noch positiv, wird sie negiert.

Sicher kann man das mittels

Code: Alles auswählen

If n > 0
  n = -n
EndIf
schreiben, aber die If-Anweisung dauert mir zu lange <)
Ich habe mir gedacht, das z.B. mittels

Code: Alles auswählen

n.b = 10

n = n | $80
zu lösen, jedoch kommt als Ergebnis dann -118 raus.
Aber warum? Das höchstwertige Bit gibt doch das Vorzeichen an und da das Bit mit dem ODER immer gesetzt wird, sollte sich doch nur das Vorzeichen ändern, scheinbar irre ich mich da jedoch :)
Denn eigentlich ist das ganze (meines Erachtens nach) nichts weiter als eine andere Schreibweise für a = a - 128.

Deswegen meine Frage: Wie stell ich es an, dass die Variable IMMER vorzeichenbehaftet ist (sprich: das höchstwertige Bit ist gesetzt)?

Und ich möchte kein Asm dafür :P

Falls jmd. Rat weiß, so solle er (oder sie) bitte sprechen.

MfG plusman

Verfasst: 06.04.2005 16:30
von freedimension
Das geht so leider nicht, denn negative Zahlen werden durch das sogenannte Zweierkomplement dargestellt ( http://de.wikipedia.org/wiki/Zweierkomplement )

Verfasst: 06.04.2005 16:38
von NicTheQuick
Das höchste Bit ist zwar ein Zeichen dafür, dass eine Variable in PureBasic negativ ist, das heißt aber noch lange nicht, dass das die einzigste Umwandlung ist, die man ausführen muss, damit eine Variable ihren Betrag beibehält und zwischen positiv und negativ wechseln kann.

Das merkst du schnell, wenn du schreibst:

Code: Alles auswählen

b.b = 127
Debug b
b + 1
Debug b
Nach deiner Logik würde jetzt in [c]b[/c] sicherlich wieder Null stehen und dann geht es bis -127 so weiter. So ist es aber nicht. Dann hätte man ja zweimal die Null drin. Einmal mit und einmal ohne Vorzeichen.

Um z.B. das Vorzeichen einer Long-Variable zu ändern, musst du folgende Varianten verwenden.

Code: Alles auswählen

n.l = 41
Debug n
n ! $FFFFFFFF + 1
Debug n
NEG n
Debug n
n = -n
Debug n
Wenn du es aber so haben willst, wie du schreibst, würde ich dir dennoch die [c]If-Abfrage-Methode[/c] ans Herz legen.

Code: Alles auswählen

n.l = -41
If n >= 0: n = -n : EndIf
Debug n
Das ist auch nicht mehr als ein ASM-Compare-Befehl. Hier der ASM-Output dazu.

Code: Alles auswählen

; n.l = -41
  MOV    dword [v_n],-41
; If n >= 0: n = -n : EndIf
  MOV    ebx,dword [v_n]
  CMP    ebx,0
  JL    _EndIf2
  MOV    ebx,dword [v_n]
  NEG    ebx
  MOV    dword [v_n],ebx
_EndIf2:

Verfasst: 06.04.2005 16:50
von Kaeru Gaman
was spricht eigentlich gegen das

Code: Alles auswählen

n = -Abs(n)
wie in der Überschrift?

Verfasst: 06.04.2005 18:50
von NicTheQuick
Die Funktion [c]Abs()[/c] ist nur für Float-Variablen gedacht und kann / sollte man nicht mit Integers benutzen. Warum es aber kein [c]AbsL()[/c] gibt oder ähnliches, weiß ich nicht. Hätte ich aber auch gerne. :roll:

Verfasst: 06.04.2005 19:23
von Kaeru Gaman
ach du Hacke....

is mir noch garnich aufgefallen...

na, das ist dann ja noch ein 'Must Have' für 4.0

Verfasst: 07.04.2005 00:31
von Froggerprogger
@Nic
Bei Dir fehlt noch die 'eigentliche' Arbeitsweise des Negierens:

Code: Alles auswählen

n = ~n + 1
(also bitweise negieren und dann plus 1 rechnen, klappt in beide Richtungen)

Verfasst: 07.04.2005 08:51
von pLuSmaN
Hm, dann bedanke ich mich für die Aufklärung. Ich war fest davon überzeugt, dass man einfach das höchstwertige Bit setzt, um die Zahl zu 'negieren'. Demnach komme ich also doch nicht um eine If-Abfrage rum.

Verfasst: 07.04.2005 09:44
von Kaeru Gaman
@Nic

könntest du bitte genauer beschreiben, unter welchen umständen ABS() mit longs fehler produziert?

ich habs nämlich schon öfter verwendet, und es hat funktioniert....

...ich bin einfach nicht auf die idee gekommen, dass es nur für floats und nicht für integers funktioniert

Verfasst: 07.04.2005 10:27
von freedimension
Kaeru Gaman hat geschrieben:@Nic

könntest du bitte genauer beschreiben, unter welchen umständen ABS() mit longs fehler produziert?

ich habs nämlich schon öfter verwendet, und es hat funktioniert....

...ich bin einfach nicht auf die idee gekommen, dass es nur für floats und nicht für integers funktioniert
Ganz einfach: Immer dann wenn die Zahlen sehr sehr groß oder sehr sehr klein werden und dann die Ungenauigkeiten von Floats zum Tragen kommen.
Floats benutzen, anders als Longs, nur einen Teil der 32 Bits zur Darstellung der eigentlichen Zahl, der Rest geht drauf für Exponent, Vorzeichen ...