Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Function für Vorzeichen? (https://www.delphipraxis.net/76719-function-fuer-vorzeichen.html)

Cöster 8. Sep 2006 16:25


Function für Vorzeichen?
 
Hi!

Gibt's ne Funktion, der man einen Real übergibt und die dann 1 zurückgibt, wenn die Zahl positiv ist, und -1, wenn sie negativ ist?

Dass man einfach schreiben kann

Delphi-Quellcode:
a := Vorzeichen(b)*5;
Bisher mach ich das so:

Delphi-Quellcode:
a := Abs(b)/b*5;
Aber das ist sicherlich nicht die eleganteste Art.

3_of_8 8. Sep 2006 16:27

Re: Function für Vorzeichen?
 
Dafür gibts die Funktion Delphi-Referenz durchsuchenSign()

Luckie 8. Sep 2006 16:28

Re: Function für Vorzeichen?
 
Delphi-Quellcode:
function IsPositive(Value: Integer): Boolean;
begin
  result := Value > 0;
end;

Cöster 8. Sep 2006 17:02

Re: Function für Vorzeichen?
 
@ 3_of_8:
Kann es sein, dass es sign auf delphi 5 noch nicht gibt?

@ Luckie:
Ich brauch nicht ne Funktion, die mir sagt, ob die Zahl positiv ist, sondern eine, die mir das Vorzeichen zurückliefert (also 1 oder -1). Sonst könnte ich ja auch ne If-Abfrage machen.

JasonDX 8. Sep 2006 17:05

Re: Function für Vorzeichen?
 
Wenns ein einfacher Term sein soll:
Delphi-Quellcode:
ord(value >= 0) * 2 - 1
Im Fall einfach in eine Funktion schmeissen ;)

greetz
Mike

[Edit] >= statt > , dann gehts auch mit 0...

3_of_8 8. Sep 2006 17:06

Re: Function für Vorzeichen?
 
Einfach Math importieren.

@Jason: Das geht nicht, wenn du ne 0 reinbekommst.

himitsu 8. Sep 2006 17:08

Re: Function für Vorzeichen?
 
also ich weiß nicht, was du hast?

Delphi-Quellcode:
If X >= 0 Then Positiv Else Negativ;
[add]
PS: das sagt mein Delphi :zwinker:
Delphi-Quellcode:
// Unit Math
function Sign(const AValue: Integer): TValueSign;
begin
  Result := ZeroValue;
  if AValue < 0 then
    Result := NegativeValue
  else if AValue > 0 then
    Result := PositiveValue;
end;

3_of_8 8. Sep 2006 17:12

Re: Function für Vorzeichen?
 
Ich hätt das jetzt so gelöst:

Delphi-Quellcode:
function Sign(const AValue: Integer): Integer;
asm
cmp eax, 0
ja @positive
cdq
mov eax, edx
ret
@positive:
mov eax, 1
end;

Klaus01 8. Sep 2006 17:27

Re: Function für Vorzeichen?
 
Delphi-Quellcode:
function Vorzeichen(Value: Integer): Char;
begin
  result:='+';
  if (Value < 0) then
    result:='-';
end;

3_of_8 8. Sep 2006 17:31

Re: Function für Vorzeichen?
 
So hat er das nicht gemeint. Er wollte eine Integer-Wert. Außerdem hast du eine unnötige Zuweisung drin und die 0 hat kein Vorzeichen, auch kein positives. ;)

Jürgen Thomas 8. Sep 2006 17:34

Re: Function für Vorzeichen?
 
Zitat:

Zitat von Cöster
@ 3_of_8:
Kann es sein, dass es sign auf delphi 5 noch nicht gibt?

@ Luckie:
Ich brauch nicht ne Funktion, die mir sagt, ob die Zahl positiv ist, sondern eine, die mir das Vorzeichen zurückliefert (also 1 oder -1). Sonst könnte ich ja auch ne If-Abfrage machen.

Wenn Du mit allen Vorschlägen - vor allem der konsequenten Lösung von 3_of_8 - nicht zufrieden bist, dann schreib Dir doch Deine Funktion selbst:
Delphi-Quellcode:
function Vorzeichen( const dValue: double ): integer;
begin
  if dValue >= 0 then
  begin
    if dValue = 0
    then Result := 0
    else Result := 1;
  end
  else Result := -1;
end;
Gruß Jürgen

Cöster 8. Sep 2006 17:45

Re: Function für Vorzeichen?
 
Dann kann ich's eigentlich auch mit Abs(Value)/Value machen. Ich dachte, da gäb's vielleicht ne fertige Funktion für, aber die selber zu schreiben (sign kennt mein delphi nicht) führt ja nur zu zusätzlichen Codezeilen. Oder hat meine Variante irgendwelche nachteile? (wenn Value 0 ist, wird der Code sowieso nicht aufgerufen, es würde also nicht durch 0 geteilt)

Jürgen Thomas 8. Sep 2006 17:53

Re: Function für Vorzeichen?
 
Zitat:

Zitat von Cöster
Dann kann ich's eigentlich auch mit Abs(Value)/Value machen.

Ich glaube nicht, dass der Compiler diese Funktion so gut optimiert wird und merkt, dass er eigentlich gar nicht rechnen muss. Denn eine Abs()-Rechnung und eine Division und ein Cast dürften aufwändiger ablaufen als zwei if-Abfragen. Du hast ja selbst gesagt:
Zitat:

Zitat von Cöster
Aber das ist sicherlich nicht die eleganteste Art.

Gruß Jürgen

3_of_8 8. Sep 2006 18:10

Re: Function für Vorzeichen?
 
Also gut, jetzt noch einmal. Sign steht in der Unit Math. Die einbinden. Das dürfte auch bei Delphi 4 oder was du hast drinsein.

Und außerdem habe ich dir schon einen Code geschrieben, der mit EINER If-Abfrage auskommt.

abs(value)/value ist ineffizient, wenn dann schon abs(value) div value, was bei einer 0 versagt, weil man nunmal nicht durch 0 teilen kann. Außerdem ist so ein div im Vergleich zu meinem Code wirklich langsam.

Zitat:

Zitat von 3_of_8
Ich hätt das jetzt so gelöst:

Delphi-Quellcode:
function Sign(const AValue: Integer): Integer;
asm
cmp eax, 0
ja @positive
cdq
mov eax, edx
ret
@positive:
mov eax, 1
end;


Hawkeye219 8. Sep 2006 18:13

Re: Function für Vorzeichen?
 
Hallo,

hier ist noch eine Assembler-Version:

Delphi-Quellcode:
function Sign2 (aValue: Integer): Integer;
asm
  sar eax,31
  or eax,1
end;
Die folgenden PASCAL-Versionen haben den Vorteil, daß man sie im BDS mit der INLINE-Direktive versehen kann. In zeitkritischen Routinen kann man damit einen zusätzlichen Geschwindigkeitsvorteil erzielen:

Delphi-Quellcode:
function SignInt (aValue: Integer): Integer; {nur für BDS: inline;}
const
  cSign: array [Boolean] of Integer = (-1, +1);
begin
  Result := cSign[aValue >= 0];
end;

function SignFloat (aValue: Double): Integer; {nur für BDS: inline;}
const
  cSign: array [Boolean] of Integer = (-1, +1);
begin
  Result := cSign[aValue >= 0];
end;
Gruß Hawkeye

3_of_8 8. Sep 2006 18:17

Re: Function für Vorzeichen?
 
Das funktioniert so nicht ganz.

Denn bei 0 hast du eine 0 im Sign-Bit und dann kriegst du bei einer 0 als Result 1.

Und wenn du das willst, geht das auch genausogut so:

Hawkeye219 8. Sep 2006 18:27

Re: Function für Vorzeichen?
 
Hallo Manuel,

Zitat:

Zitat von Cöster
...die dann 1 zurückgibt, wenn die Zahl positiv ist, und -1, wenn sie negativ ist?

Ich habe das so verstanden, daß er zwei mögliche Ergebnisse erwartet. Die 0 gilt dabei als positive Zahl. Aber Cöster wollte ja sowieso keine Funktion für Integer-Zahlen...

PS: In deiner Assembler-Routine solltest du das "JA" durch ein "JG" ersetzen. :wink:

Gruß Hawkeye

Cöster 8. Sep 2006 18:34

Re: Function für Vorzeichen?
 
Zitat:

Zitat von 3_of_8
Also gut, jetzt noch einmal. Sign steht in der Unit Math. Die einbinden. Das dürfte auch bei Delphi 4 oder was du hast drinsein.

Math ist eingebunden, er kennt Sign trotzdem nicht.
Zitat:

Zitat von 3_of_8
abs(value)/value ist ineffizient, wenn dann schon abs(value) div value

Seit wann läuft div auch mit Reals?
Zitat:

Zitat von 3_of_8
, was bei einer 0 versagt, weil man nunmal nicht durch 0 teilen kann.

wie gesagt, dazu wird es nie kommen.
Zitat:

Zitat von 3_of_8
Ich hätt das jetzt so gelöst:

Delphi-Quellcode:
function Sign(const AValue: Integer): Integer;
asm
cmp eax, 0
ja @positive
cdq
mov eax, edx
ret
@positive:
mov eax, 1
end;

Der Code ist sicherlich nicht schlecht, aber (das kannst du nicht wissen) ich kann kein Assembler und ich möchte keinen Code schreiben, den ich nicht verstehe. :wink:

Ich hab mir nach euren Tipps jetzt doch ne Function gebastelt:
Delphi-Quellcode:
function Sign(Value: Real): Integer;
begin
  If Value < 0 then
    result := -1
  else
    result := 1;
end;

himitsu 8. Sep 2006 18:39

Re: Function für Vorzeichen?
 
Aber eigentlich sollte D5 Sign kennen (siehe Unit Math)

PS: @Threadersteller

rate mal, was deine Variante mit der Divition sagt, wenn man der eine 0 gibt :warn:

3_of_8 8. Sep 2006 18:47

Re: Function für Vorzeichen?
 
Er sagte, es kommt nie dazu.

Und @Cöster: Nimm nie ein if, wenn du stattdessen eine arithmethische Operation kriegst. Ifs bremsen den Prozessor ab.

Flocke 8. Sep 2006 19:02

Re: Function für Vorzeichen?
 
Zitat:

Zitat von 3_of_8
Nimm nie ein if, wenn du stattdessen eine arithmethische Operation kriegst. Ifs bremsen den Prozessor ab.

:roll: Was denkst du denn, was ein ja bzw. jg in Assembler ist?

Die Version von Hawkeye219 ist laufzeittechnisch schon optimal - schade dass man Assembler-Funktionen nicht inline machen kann...

// Nachtrag: ich Dummkopf...

Delphi-Quellcode:
function Sign(Value: Integer): Integer; inline;
begin
  Result := (Value shr 31) or 1;
end;

Cöster 8. Sep 2006 19:08

Re: Function für Vorzeichen?
 
Zitat:

Zitat von himitsu
Aber eigentlich sollte D5 Sign kennen (siehe Unit Math)

In der Uses-Klausel steht Math und trotzdem schreibt er mir undefinierter Bezeichner, sobald ich was von Sign schreibe.

Kann es vielleicht sein, dass die Unit Math für spätere Delphi-Versionen überarbeitet wurde?
Übrigens: TryIntToStr kennt Delphi 5 Standard auch nicht.

Zitat:

Zitat von 3_of_8
Nimm nie ein if, wenn du stattdessen eine arithmethische Operation kriegst.

Was meinst du damit?

Hawkeye219 8. Sep 2006 19:19

Re: Function für Vorzeichen?
 
@Flocke

SHR ist in Delphi ein vorzeichenloser Shift nach rechts - unabhängig von der Art des Operanden. Das Gegenstück (ASR) haben die Borländer leider nicht implementiert.

@Cöster:

Die Unit Math wurde/wird ständig erweitert, die Sign-Funktionen wurden in Delphi 6 hinzugefügt. Eine Erklärung zu Manuels Aussage findest du in der Wikipedia.

Gruß Hawkeye

Flocke 8. Sep 2006 19:41

Re: Function für Vorzeichen?
 
Zitat:

Zitat von Hawkeye219
SHR ist in Delphi ein vorzeichenloser Shift nach rechts - unabhängig von der Art des Operanden.

Ich habe gerade extra Delphi noch einmal angeschmissen, um mich zu vergewissern. Leider hast du Recht - anders als z.B. in C/C++ ist shr immer vorzeichenlos.

Zitat:

Zitat von Hawkeye219
Das Gegenstück (ASR) haben die Borländer leider nicht implementiert.

Du meinst bestimmt SAR, oder? :mrgreen: :zwinker:

3_of_8 8. Sep 2006 19:45

Re: Function für Vorzeichen?
 
@Flocke: Das weiß ich. Aber ich verwende nur ein if anstatt von zwei, was das ganze wieder beschleuningt.

Cöster 8. Sep 2006 19:47

Re: Function für Vorzeichen?
 
Zitat:

Zitat von Hawkeye219
Eine Erklärung zu Manuels Aussage findest du in der Wikipedia.

Jetzt weiß ich trotzdem noch nicht, was eine arithmetische Operation ist. Statt wessen krieg ich die?

Dax 8. Sep 2006 19:48

Re: Function für Vorzeichen?
 
Zitat:

Zitat von Flocke
Delphi-Quellcode:
function Sign(Value: Integer): Integer; inline;
begin
  Result := (Value shr 31) or 1;
end;

Nenn mich blöd, aber warum noch das or?

edit: :wall: Ja, ich hab mir das shr als sar vorgestellt beim lesen, aber warum das or muss, ist mir erst später aufgefallen... Nennt mich nicht blöd, bindet mir ein Schild um :|

Cöster 8. Sep 2006 19:49

Re: Function für Vorzeichen?
 
Zitat:

Zitat von 3_of_8
@Flocke: Das weiß ich. Aber ich verwende nur ein if anstatt von zwei, was das ganze wieder beschleuningt.

Benutze ich nicht auch nur eins?
(if then else)

3_of_8 8. Sep 2006 19:54

Re: Function für Vorzeichen?
 
Ganz einfach: Wenn er eine 0 oder eine 1 reinkriegt, hat er eine 0 als Ergebnis. Das muss aber eine 1 sein, darum or 1.

@Cöster: Eigentlich hätte ich schreiben sollen eine logisch-arithmetische Operation. Dazu gehören +-*/, div und mod und außerdem not, and, or, xor, shl, shr, sar und vllt hab ich noch welche Vergessen.

Auf Assemblerebene gibts noch ein paar zusätzliche wie z.B. cdq, was allerdings eher ein Cast zu einem Int64 ist.

Diese Operationen bremsen im Gegenteil zu einem if den Prozessor nicht ab. (Pipelining)

Das ist auch der Grund, warum z.B. die Funktion abs nicht mithilfe von Ifs implementiert ist, sondern mit einem cdq und einem xor.

Noch ein Beispiel:
Du willst eine Variable zwischen 0 und 1 umschalten, also wenn a=0 dann a:=1 ansonsten a:=0;
Das könnte man jetzt so machen:
if a=0 then a:=1 else a:=0;

Man könnte es aber auch so machen:
a:=1-a;

Zweiteres geht deutlich schneller.

Zu deinem einen If: 1. lässt sich das auch noch vermeiden und 2. bekommst du mit deiner Funktion NICHT das Vorzeichen.

Cöster 8. Sep 2006 20:46

Re: Function für Vorzeichen?
 
Zitat:

Zitat von Cöster
Delphi-Quellcode:
function Sign(Value: Real): Integer;
begin
  if Value < 0 then
    result := -1
  else
    result := 1;
end;

Zitat:

Zitat von 3_of_8
Zu deinem einen If: 1. lässt sich das auch noch vermeiden und 2. bekommst du mit deiner Funktion NICHT das Vorzeichen.

Sondern? Natürlich, ich bekomme nicht - oder +, aber -1 oder +1. Das ist auch alles, was ich will. Ich brauch den Befehl "hänge an a das Vorzeichen von b dran" und dafür schreib ich dann
a := sign(b)*a;

Wie lässt sich das if denn in der Funktion verhindern (ohne Assembler-Code)? Mehr als
result := value/abs(value)
fällt mir nicht ein. Aber das soll ja noch langsamer sein, als ein if.
Wie kann man das denn ohne if (und ohne Assembler) schreiben? :gruebel:

himitsu 8. Sep 2006 20:57

Re: Function für Vorzeichen?
 
Zitat:

Zitat von Hawkeye219
Die Unit Math wurde/wird ständig erweitert, die Sign-Funktionen wurden in Delphi 6 hinzugefügt.

OK, dann halt nicht .... mir war nur o, als gab's dat in meinem D4 auch schon :oops:

Dax 8. Sep 2006 21:09

Re: Function für Vorzeichen?
 
Zitat:

Zitat von Cöster
Wie kann man das denn ohne if (und ohne Assembler) schreiben? :gruebel:

Delphi-Quellcode:
function Sign(i: Integer): Integer;
begin
  Result := (0 - (i shr 31)) or 1;
end;

Hawkeye219 8. Sep 2006 21:24

Re: Function für Vorzeichen?
 
Hallo Cöster!

Zitat:

Natürlich, ich bekomme nicht - oder +, aber -1 oder +1. Das ist auch alles, was ich will.
Manuel wollte dich darauf aufmerksam machen, daß die gängigen Vorzeichen-Funktionen für die Zahl 0 den Wert 0 als "Vorzeichen" liefern. Deine Funktion liefert in diesem Fall den Wert 1, betrachtet die Null also als positive Zahl.

Zitat:

Wie kann man das denn ohne if (und ohne Assembler) schreiben?
Ich hatte im Beitrag #15 eine mögliche Lösung vorgestellt (für Integer- und Double-Werte), weil ich auch von einer zweiwertigen Funktion ausging. Obwohl Vergleichsoperatoren verwendet werden, enthält der erzeugte Assemblercode keine Sprungbefehle.

@Dax: so geht's :thumb:

Gruß Hawkeye

3_of_8 8. Sep 2006 21:25

Re: Function für Vorzeichen?
 
Sondern? Natürlich, ich bekomme nicht - oder +, aber -1 oder +1. Das ist auch alles, was ich will. Ich brauch den Befehl "hänge an a das Vorzeichen von b dran" und dafür schreib ich dann
a := sign(b)*a;

Wie lässt sich das if denn in der Funktion verhindern (ohne Assembler-Code)? Mehr als
result := value/abs(value)
fällt mir nicht ein. Aber das soll ja noch langsamer sein, als ein if.
Wie kann man das denn ohne if (und ohne Assembler) schreiben? :gruebel:[/quote]

Du bekommst bei einer 0 eine +1 raus. Eine 0 hat aber kein Vorzeichen, folgerichtig muss also bei einer 0 eine 0 rauskommen.

Das geht natürlich dann nicht ohne if, aber mit einem statt 2.

Christian Seehase 8. Sep 2006 21:50

Re: Function für Vorzeichen?
 
Moin Zusammen,

ist ja schön, dass ihr so viele Vorschläge macht, wie man das bei integer-Werten machen kann, Cöster sucht das aber für Real ;-)

3_of_8 8. Sep 2006 21:53

Re: Function für Vorzeichen?
 
Er kann ihn ja vorher truncaten.

Christian Seehase 8. Sep 2006 21:57

Re: Function für Vorzeichen?
 
Moin Manuel,

das dürfte nicht viel helfen, wenn der Wert zwischen -1 und +1 liegt.

Dax 8. Sep 2006 21:57

Re: Function für Vorzeichen?
 
Zitat:

Zitat von Christian Seehase
Moin Zusammen,

ist ja schön, dass ihr so viele Vorschläge macht, wie man das bei integer-Werten machen kann, Cöster sucht das aber für Real ;-)

Nuuun *grübel* ;)

Delphi-Quellcode:
function Sign(e: Extended): Integer;
begin
  Result := (0 - (e shr 79)) or 1;
end;

Hawkeye219 8. Sep 2006 22:06

Re: Function für Vorzeichen?
 
Dax, diesmal muß ich dich enttäuschen - SHR erwartet einen ganzzahligen Operanden.

Zitat:

Zitat von Christian Seehase
Cöster sucht das aber für Real

Zitat:

Zitat von Hawkeye219
Ich hatte im Beitrag #15 eine mögliche Lösung vorgestellt (für Integer- und Double-Werte)

Gruß Hawkeye

Dax 8. Sep 2006 22:11

Re: Function für Vorzeichen?
 
Zitat:

Zitat von Hawkeye219
Dax, diesmal muß ich dich enttäuschen - SHR erwartet einen ganzzahligen Operanden.

Oops, sowas hab ich mir schon gedacht :( Da hab ich wohl schneller getippt als gedacht. ;)

Gings denn so?

Delphi-Quellcode:
function Sign(e: Extended): Integer;
type
  PExtendedRec = ^TExtendedRec;
  TExtendedRec = record
    case Integer of
      0: (e: Extended);
      1: (a: Array[0..9] of Byte);
  end;
begin
  Result := (0 - (PExtendedRec(@e)^.a[0] shr 7)) or 1;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:47 Uhr.
Seite 1 von 2  1 2      

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