Zahl immer negativ (-Abs ())

Für allgemeine Fragen zur Programmierung mit PureBasic.
pLuSmaN
Beiträge: 10
Registriert: 11.09.2004 12:32

Zahl immer negativ (-Abs ())

Beitrag 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
Benutzeravatar
freedimension
Admin
Beiträge: 1987
Registriert: 08.09.2004 13:19
Wohnort: Ludwigsburg
Kontaktdaten:

Beitrag von freedimension »

Das geht so leider nicht, denn negative Zahlen werden durch das sogenannte Zweierkomplement dargestellt ( http://de.wikipedia.org/wiki/Zweierkomplement )
Beginne jeden Tag als ob es Absicht wäre!
Bild
BILDblog
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8808
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag 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:
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

was spricht eigentlich gegen das

Code: Alles auswählen

n = -Abs(n)
wie in der Überschrift?
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8808
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag 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:
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ach du Hacke....

is mir noch garnich aufgefallen...

na, das ist dann ja noch ein 'Must Have' für 4.0
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Froggerprogger
Badmin
Beiträge: 855
Registriert: 08.09.2004 20:02

Beitrag 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)
!UD2
pLuSmaN
Beiträge: 10
Registriert: 11.09.2004 12:32

Beitrag 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.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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
Benutzeravatar
freedimension
Admin
Beiträge: 1987
Registriert: 08.09.2004 13:19
Wohnort: Ludwigsburg
Kontaktdaten:

Beitrag 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 ...
Beginne jeden Tag als ob es Absicht wäre!
Bild
BILDblog
Antworten