Seite 1 von 1
Immer noch kein Abs() für Integer
Verfasst: 02.07.2006 10:40
von Kaeru Gaman
warum gibt es immer noch kein Abs() für integer?
klar, das ist nicht schwierig selbst zu implementieren, aber das ärgerliche ist,
dass das son rumgedaddel ist, das MSB zu löschen, wenn man nicht weiß,
ob der übergebene wert nun Word, Long oder Quad ist.
ich bin grad dabei, ein paar macros zu schreiben, und ich bräuchte mal da ein Abs().
eigentlich hatte ich nicht vor, mehrere macros zu schachteln bzw. das macro unnötig zu verkomplizieren.
ich finds einfach ärgerlich.
PS:
und ich stelle grad fest, dass ich nich einfach mal so ein macro schreiben kann, was das MSB löscht, da eben an Abs() auch ausdrücke übergeben werden können, und die kann man nicht als Argumente für SizeOf() verwenden. also doch ne boole'sche lösung.
Verfasst: 02.07.2006 13:22
von mk-soft
MSB löschen?,
Da kommt ein falsches Ergebnis herraus. Alle Bits Invertieren und dann plus Eins oder nur Mal minus Eins
FF
P.S.
Code: Alles auswählen
Procedure.w AbsW(value.w)
If value < 0
ProcedureReturn ~value + 1
EndIf
EndProcedure
Procedure.l AbsL(value.l)
If value < 0
ProcedureReturn ~value + 1
EndIf
EndProcedure
Debug AbsW(2)
Debug AbsW(-2)
Debug AbsW(-32767)
Debug AbsL(2)
Debug AbsL(-2)
Debug AbsL(-123456789)
Verfasst: 02.07.2006 13:39
von Kaeru Gaman
äh.. ja, mit If alles kein thema, ich brauch aber ein Macro.
klar könnte ich den funktionsaufruf ins macro einbaun, darauf würde ich aber gerne verzichten, wenn möglich.
(wenn möglich, es wird aber wohl ziemlich komplex)
gibt es keine einfache operation, die man auf positive und negative werte anwenden kann, um das korrekte ergebnis rauszubekommen?
re: MSB löschen
stimmt ja, is ja ganz was anderes.. denkfehler. uralter denkfehler. eigentlich hatte ich das schon seit jahrzehnten begriffen, es war mir nur entglitten.
Verfasst: 02.07.2006 20:51
von helpy
Hier noch eine kleines Abs-Macro, das nicht ganz so rechenintensiv ist:
Code: Alles auswählen
Macro AbsX(x)
( ((x>>(SizeOf(x)*8-1)) | 1 ) * x)
EndMacro
!!! Funktioniert aber nur für Variablen vom Typ .b, .w, .l und .q ... funktioniert nicht für Ausdrücke und Konstanten!
Angetestet mit folgendem Code:
Code: Alles auswählen
Macro test(x,wert)
x = wert
Debug "Size = " + Str(SizeOf(x)) + " :: Wert = " + Str(x) + " :: Abs = " + Str(AbsX(x))
EndMacro
b.b
w.w
l.l
q.q
test(b,10)
test(w,1000)
test(l,100000)
test(q,10000000)
test(b,0)
test(w,0)
test(l,0)
test(q,0)
test(b,-10)
test(w,-1000)
test(l,-100000)
test(q,-10000000)
test(b,-1)
test(w,-1)
test(l,-1)
test(q,-1)
cu, helpy
Verfasst: 02.07.2006 21:33
von Kaeru Gaman
hups, diesen thread hatte ich ja ganz vergessen...
nuja, das macro müsste auf jeden fall ausdrücke verarbeiten können...
also, hier ist mein macro, das auch für ausdrücke funktioniert:
Code: Alles auswählen
Macro AbsEx(Expression)
((Expression) * (-1 * ((Expression) < 0 Or 0)) + ((Expression) >= 0 Or 0) * (Expression))
EndMacro
ist aber sehr rechenintensiv, da der ausdruck 4x vorkommt und auch 4x ausgewertet wird.
die Proc mit If ist wesentlich schneller.
ein macro kann halt nicht so etwas wie einen rückgabewert haben, außer wie in diesem fall, das komplette macro ist ein ausdruck der das gewünschte ergebnis evaluiert.
ich hab jetzt halt doch ne Proc genommen *duck*
da ichs in ein anderes Macro einbauen wollte, konnte ich an der stelle dann doch eine Proc benutzen...
http://www.purebasic.fr/german/viewtopi ... 9743#99743
Verfasst: 02.07.2006 22:51
von helpy
Du kannst die Formel etwas vereinfachen:
Code: Alles auswählen
Macro AbsEx(Expression)
( ( ((Expression) >= 0 Or 0) - ((Expression) < 0 Or 0) ) * (Expression) )
EndMacro
Verfasst: 03.07.2006 08:53
von Kaeru Gaman
ah.. cool
stimmt, meine "denkschlappe"
und jetzt fällt mir die noch kürzere lösung ein:
Code: Alles auswählen
Macro AbsEx(Expression)
( ( ((Expression) >= 0 Or 0) *2 - 1 ) * (Expression) )
EndMacro