![]() |
Vorzeichen entfernen
Hi,
Bis jetzt habe ich zum berechnen des Betrages immer folgenden Code benutzt:
Delphi-Quellcode:
Ich schätze, dass es eine Geschicktere Lösung geben wird.
Zahl:=sqrt(Zahl*Zahl)
Welche könnte das sein? |
Re: Vorzeichen entfernen
ABS()
|
Re: Vorzeichen entfernen
Delphi-Quellcode:
Achja: Uses System.
absoluterwert := Abs(-5);
Edit Nachtrag: Ich komm mir heute langsam vor... |
Re: Vorzeichen entfernen
Danke. Genau danach hab ich gesucht.
|
Re: Vorzeichen entfernen
uses System? O_o
Phoenix, war das ironisch gemeint? Wenn nein, System ist IMMER eingebunden. |
Re: Vorzeichen entfernen
Ich bin heut einfach nicht mehr ganz wach... :roteyes:
|
Re: Vorzeichen entfernen
Ich auch.
Ich bin heut einfach nicht mehr ganz wach... Rotating Eyes |
Re: Vorzeichen entfernen
die wurzel ziehen ist nicht umbedingt das beste für die cpu. ohne abs wäre eine Lösung zu schauen ob die Zahl < 0 ist und wenn dem der fall ist * -1 zu rechnen. bzw. einfach das minus vorranstellen (denn - + - ergibt +)
Delphi-Quellcode:
if zahl < 0 then
zahl := -zahl; |
Re: Vorzeichen entfernen
...wobei abs() um einiges schneller ist. Wenn der Compiler es inlinet (was er vermutlich tun wird), braucht es sogar nur 3 Assemblerbefehle (bei Integern, bei Float wäre es ein FPU-Befehl), und zwar ein cdq, ein xor und ein sub. Ein if und eine Subtraktion sind dadurch langsamer.
|
Re: Vorzeichen entfernen
Zitat:
kannte das nur als - * - = + da würde ja -5 + -2 +7 ergeben, richtig? oder vielleicht +3... :gruebel: das minus voranstellen macht ja auch ne multiplikation sicher nur ein schreibfehler, aber wollte das nicht so stehen lassen... ein etwas exotischer weg wäre sicher auch, das höchstwertige Bit auf 0 zu setzen :) Gruß Frank |
Re: Vorzeichen entfernen
@frank: Nicht nur exotisch, sondern auch falsch.
-1: $FFFFFFFF Oberstes Bit auf 0 gesetzt: $7FFFFFFF Und $7FFFFFFF ist 2^31-1, also ungefähr 2 Mrd. und nicht, wie gewünscht, 1. Wenn schon, dann müsste man es so machen:
Delphi-Quellcode:
Oder, der schnellere Assembler-Weg:
if x<0 then x:=not x + 1;
Code:
cdq eax
xor eax, edx sub eax, edx |
Re: Vorzeichen entfernen
Zitat:
|
Re: Vorzeichen entfernen
gut, dann hatte ich das mal falsch verstanden, :roll:
dachte bei signed wird das vorzeichen im höchstwertigen Bit gespeichert und der rest bleibt... jetzt hab ich mich aber mal blamiert... :oops: aber jetzt wo ihrs sagt, fällt mir grade ein, dass ich beim Zerlegen von Binärdateien schon drüber gestolpert bin, dass 0xFFFFFFFF = -1 ist. stimmt das
Delphi-Quellcode:
immer? also bei allen signed datentypen?
if x<0 then x:=not x + 1;
auch wenn mir der asm-weg noch bisschen Probleme bereitet, trotz asm buch vor mir... wenn ich das richtig verstehe, müsste cdq ja das höchstwertige bit von eax in alle bits von edx schreiben.... also
Code:
bzw.
edx eax
$FFFFFFFF $FFFFFFFF
Code:
xor setzt dann bei ersterem eax auf $0, da eax=edx.
$00000000 $7FFFFFFF
jetzt subtrahiere ich edx von eax also $0-$FFFFFFFF...und da kommt 1 raus? beim zweiten wird bei xor einfach nur edx nach eax kopiert (unterste 31 bit verschieden), wenn ich nun edx von eax subtrahiere kommt doch 0 raus wo hab ich da jetzt grade den denkfehler? Gruß Frank |
Re: Vorzeichen entfernen
Also, ganz langsam:
Bei allen vorzeichenbehafteten Typen gilt die Regel -x=not x + 1. Jedenfalls bei allen auf x86-Prozessoren, und ich vermute mal, bei so ziemlich allen anderen verbreiteten Binärprozessoren auch, weil so ziemlich alle das Zweierkomplement verwenden. cdq eax schreibt das Vorzeichenbit von eax in alle Bits von edx. cdq steht für "Convert to quad word", es führt also praktisch eine Umwandlung eines 32-Bit-Integers in einen Int64 durch. xor eax, edx macht im Fall edx=$00000000 gar nichts. eax bleibt also gleich, wenn es >=0 ist. xor eax, edx macht im Fall edx=$FFFFFFFF einfach ein "not eax", da jedes Bit auf 1 gesetzt wird, wenn es 0 ist und auf 0, wenn es 1 ist. sub eax, edx macht im Fall edx=$00000000 wieder nichts, da eax-0=eax ist. sub eax, edx macht im Fall edx=$FFFFFFFF einfach "eax+1", da eax-(-1)=eax+1 ist. Also haben wir im Endeffekt eine "Entfernung" des Vorzeichens, und zwar ganz ohne Sprünge, die unser prozessorinternes Pipelining stören könnten. |
Re: Vorzeichen entfernen
Zitat:
-5 - -2 = -3 als Beispiel einer Subtraktion von negativen Zahlen |
Re: Vorzeichen entfernen
Zitat:
-5 - -12 = 7 |
Re: Vorzeichen entfernen
Zitat:
.oO(sollte das wohl das nächste Mal entsprechend kennzeichnen) Frank |
Re: Vorzeichen entfernen
Zitat:
-X + -Y = +Z sondern ich hab geschrieben - + - = + |
Re: Vorzeichen entfernen
Zitat:
X - -Y => X + Y <offtopic> kann man das "-" und "+"nicht fett darstellen? Hier wird das FETT ignoriert:
Code:
X [b]- -[/b]Y => X [b]+[/b] Y
|
Re: Vorzeichen entfernen
@Topic: Gehen tut auch:
Delphi-Quellcode:
oder
Zahl:=Zahl*Sign(Zahl);
Delphi-Quellcode:
[edit]
If Zahl<0 Then Zahl:=Zahl-2*Zahl;
oder:
Delphi-Quellcode:
ZahlStr:=IntToStr(Zahl);
ZahlStr:=Copy(ZahlStr,Succ(Pos('-',ZahlStr)),Length(ZahlStr)); Zahl:=IntToStr(ZahlStr); |
Re: Vorzeichen entfernen
ich wollte damit ausdrücken das ein vorrangestelltes - das gleiche bewirkt wie * -1
-PositiveZahl = NegativeZahl -NegativeZahl = PositiveZahl |
Re: Vorzeichen entfernen
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:19 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz