Entwickler-Ecke

Algorithmen, Optimierung und Assembler - Vorzeichen durch 1;0


F34r0fTh3D4rk - Di 08.01.08 16:51
Titel: Vorzeichen durch 1;0
Hi, ich habe folgende kleine Funktion:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
  function Vorzeichen(vz: integer): integer;
  begin
    if vz = 0 then
      result := 1 else
        if vz = 1 then
          result := -1 else
            result := 0;
  end;

Allerdings dachte ich, dass dies vielleicht eleganter geht. Ich habe eine Variable, die entweder 0 oder 1 ist,
aus 0 soll 1 werden und aus 1 wird -1. (0 -> kein vorzeichen; 1 -> mit minus);
verwendet wird der code momentan so:

Delphi-Quelltext
1:
  a * vorzeichen(i);  // i ist 0 oder 1                    


mfg


zuma - Di 08.01.08 16:56

vielleicht so? :

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
function Vorzeichen(vz: integer): integer;
begin
  if vz = 0 then
    result := 1 
  else
   result := -vz; // wenn der wert als minus zurückgegeben werden soll
   result := -1// wenn immer minus 1 gegeben werden soll
end;


Allesquarks - Di 08.01.08 16:56

Nunja das ist ja nicht wirklich lang ich persönlich würde nicht die erste if Abfrage mit der Null machen, da man damit ja nur einen einzigen Wert abdeckt. Setzt man hier direkt größer Null hat man schon die Hälfte aller Werte mit einem Vergleich abgearbeitet => schnell => elegant.
Falls es dir hilft kannst du dir ja direkte boolsche Zuweisungen anschauen so alla

Delphi-Quelltext
1:
myvar:=integer(var1>0);                    


noidic - Di 08.01.08 16:59

(ungetestet)


Delphi-Quelltext
1:
  a := sign(i - 0,5) * -1;                    


liefert bei 0:
a:= sign( -0,5) * -1 = -1 * -1 = 1

und bei 1:
a:= sign(0,5) * -1 = 1 * -1 = -1


F34r0fTh3D4rk - Di 08.01.08 17:03

danke, schon nicht schlecht, vielleicht gehts noch einfacher ? (bzw. noch rechenleistungssparender ?)

mfg


Yogu - Di 08.01.08 17:10


Delphi-Quelltext
1:
2:
Result := 1;
if VZ=1 then dec(VZ, 2);

Vielleicht so?


F34r0fTh3D4rk - Di 08.01.08 17:17

am besten wäre, dass ich keine function brauche, also ohne if etc.

mfg


jackle32 - Di 08.01.08 17:36

Also wenn du sicher nur 0 und 1 an die Funktion übergeben wird geht es einfache so


Delphi-Quelltext
1:
2:
3:
4:
function vorzeichen (vz : integer) : integer;
begin
  result := -vz;
end;


Denn aus 0 wird wieder null und aus 1 wird dann -1

Noch einfacher, wenn du dieses Vorzeichen wirklich nur einmal wie oben beschrieben benutzt:


Delphi-Quelltext
1:
a * -i;                    


so geht es ganz ohne extra funktion

Gruß Jack


zongo-joe - Di 08.01.08 17:40

@jackle -> hilft nicht, er will ja mit dem vz multiplizieren da macht die 0 alles kaputt.

mit ner einfachen rechenoperation geht das imho nicht.

klingt ja nach messwerten oder nem s/w bild ->

wie generierst du denn die werte, villeicht kannst du da statt 0/1 direkt 1/-1 erzeugen...


F34r0fTh3D4rk - Di 08.01.08 17:42

die werte werden so "generiert":

Delphi-Quelltext
1:
  for i := 0 to 1 do                    

ich bearbeite damit ein array und muss je nach 0 oder 1 entscheiden ob ich addiere oder subtrahiere und das hätte ich gerne ohne if ;) da ich schon so sachen wie

Delphi-Quelltext
1:
(i xor 1)                    

benutze (not i scheint nicht zu gehen)

mfg


zongo-joe - Di 08.01.08 17:47

also wenn ich dich richtig verstanden habe, wird das array einmal mit i=0 bearbeitet, also wird arry[]:=array[]*1 gerechnet..
beim zweiten durchlauf wird alles mit -1 multipliziert...

na dann mach doch einfach einen durchlauf der schleife mit -1, bei der 0 passiert doch eh nix...


platzwart - Di 08.01.08 17:50

user profile iconF34r0fTh3D4rk hat folgendes geschrieben:
die werte werden so "generiert":

Delphi-Quelltext
1:
  for i := 0 to 1 do                    



also einmal '+' und einmal '-' als vorzeichen? dann würd ich sagen, wäre loopunrolling das mit abstand schnellste:

den inhalt der for-schleife kopieren. einmal '+' und einmal '-' einsetzen, schneller gehts nimmer ;)


F34r0fTh3D4rk - Di 08.01.08 17:51

ich möchte den code so kurz wie möglich halten (gleichzeitig soll er natürlich effizient bleiben). ;) das ist zweck der ganzen geschichte :P


mfg


zongo-joe - Di 08.01.08 17:57

na dann mach doch:

arraywert - 2*i*arraywert

dann kriegst du zwar nicht das vz aber den wert mit dem du rechnen willst


Kha - Di 08.01.08 17:58


Delphi-Quelltext
1:
1 - 2 * i                    

:gruebel: ?

Edit: Das müssen Millisekunden gewesen sein :P


Yogu - Di 08.01.08 18:01


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
i := -1;
while i <= 1 do
begin
  {...}
  Variable := Positiver_Wert*i;
  {...}
  inc(i, 2);
end;

So bekommst du einmal einen negativen Wert, dann einen positiven.


platzwart - Di 08.01.08 18:14

kommt drauf an, was dir wichtiger ist. bei performance ist loopunrolling das beste, für minimalen code dann einen der anderen vorschläge... (wobei der compiler wahrscheinlich eh loopunrolling vornehmen wird :D )


Marc. - Di 08.01.08 18:16

Sollte funktionieren: (a*-1or 1))
Beim Array: (-a[x] or 1)

Grüße
Marc


zongo-joe - Di 08.01.08 18:48

...nachdem ich jetzt den knoten in meinem hirn entknödelt habe:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
function Vorzeichen(vz: integer): integer;
  begin

    result = 1 - (2 * vz);

  end;


Allesquarks - Di 08.01.08 20:01

Wenn du wirklich nur 0 und 1 übergibst mit Null sonst funktioniert es schon nicht mehr:

shl um 1 => not => add 2

Aber es wäre auf jeden fall permformanter diese Trivialmultiplikationen nicht durchzuführen und mit den ifs weiterzumachen.

aber gib mal mehr informationen zu deinem Problem ist a immer positiv sind die Null und 1 willkürlich könntest du da auch andere Repräsentationswerte nehmen?

@Platzwart: Loopunrolling ist schon eine extreme Optimierung und gar nicht bei jeder Schleife möglich und bei Delphi wahrscheinlich gar nicht dabei.


zongo-joe - Sa 12.01.08 14:31

ich habs mal aus reiner verletzter eitelkeit :wink: getestet:

die multiplikation ist zunindest auf meinem notebook 1,5 - 2 mal schneller als die if-abfrage (die wollte er ja eh vermeiden)
... und er liefert sicher immer nur 0 oder 1 (s.o.)

:dance:

... aber scheint isch je eh erledigt zu haben


platzwart - Sa 12.01.08 15:16

Zitat:

@Platzwart: Loopunrolling ist schon eine extreme Optimierung und gar nicht bei jeder Schleife möglich und bei Delphi wahrscheinlich gar nicht dabei.


Extreme Optimierung??? Bei Delphi nicht dabei??? Dann wäre ich aber sehr schwer enttäuscht, ist ja wirklich kein Hexenwerk und kann im Extremfall den Code stark beschleunigen...