DMUG-Archiv 2006

Frühere   Chronologischer Index   Spätere
Vorherige   Thematischer Index   Nächste

Re: Antwort: Re: Indizierung von Tables mit Null beginnen.

Guten Abend Jens-Peer, Richard, Robert,

die Lösung First[RotateLeft[x, n]] IST tatsächlich zu allem Überfluss ein ineffizientes Grauen - besten Dank für den Hinweis, Jens-Peer. Mit einem ähnlichen Codeschnipsel

In[17]:=
With[{tanZ = 5000, elemenZ = 200000},
 vec = Table[Unique[k], {elemenZ}];
 If[ToString[vec[[0]]] === "List",
   Print["einsbasiert"];
   Timing[Table[o = Random[Integer, {1, elemenZ}]; vec[[o]], {tanZ}]; ],
   Print["nullbasiert"];
   Timing[Table[o = Random[Integer, {0, elemenZ - 1}]; vec[[o]], {tanZ}]; ]
 ]
] hat ein Rechner aus dem Jahre 2003 mit XP nullbasiert 472.625 Sekunden benötigt, dagegen einsbasiert im besten Fall 0.016 Sekunden, da liegt ein Faktor 29539 dazwischen.

Man kann auf RotateLeft[] verzichten:

In[19]:=
Unprotect[Part]
Part /: Part[x_List, n_Integer] := First[Take[x, {n + 1, n + 1}]]
Part /: Part[x_List, n__Integer] := Fold[Part, x, {n}] /; Length[{n}] > 1
Part /: Part[x_List, l_List] := (Part[x, #]& /@ l) /; Length[l] > 0 && VectorQ[l, IntegerQ]
Protect[Part]

nun sind die Zeiten nullbasiert mit obenstehendem Codeschnipsel 0.047 s, 0.062 s, 0.063 s bei drei aufeinanderfolgenden Versuchen. Trotzdem sprechen einige Gründe dagegen, einer built-in Funktion wie Part[] eigene Definitionen voranzusetzen:

(1) Da Part[] per default einsbasiert ist, kann mit -1 das letzte Element geholt werden. Das geht bei Verwendung von First[RotateLeft[x, n]] immer noch, ist jedoch nullbasiert völlig unlogisch.

(2) Schon nach kurzer Zeit kann Verwirrung entstehen, wenn man sich der (eigenen) Definitionen nicht (mehr) bewusst ist:

Bei der Definition: Part /: Part[x_List, n_Integer] := First[Take[x, {n + 1, n + 1}]]
kommt:

In[34]:= a = BesselJZeros[Pi, 8]
Out[34]= {110.92, 29.1169, 6.5531, 19.6119, 38.5822, 44.8829, 38.5822, 32.2747}
In[35]:= a[[8]]
From In[35]:= Take::take : Cannot take positions 9 through 9 in {...}

Okay. Wenn man die Fehlermeldung nicht sehen will und kurzerhand
Part /: Part[x_List, n_Integer] := First[Take[x, {n + 1, n + 1}]] /; n < Length[x]

definiert, dann kommt logischerweise mit a[[0]] wieder das erste Element, aber

In[38]:= a[[8]]
Out[38]= 32.2747

mit anderen Worten, ein Mix zwischen dem unter der Bedingung n < Length[x] erzwungenen nullbasierten Verhalten und dem Defaultverhalten: a[[8]] wird einsbasiert ausgegeben.

(3) You can make an assignment like t[[i]] = value to modify part of an expression. Sieht man sich das nullbasiert an:

In[67]:= a[[0]] = 99
Out[67]= 99

In[68]:= a
Out[68]= 99[110.92, 29.1169, 6.5531, 19.6119, 38.5822, 44.8829, 38.5822, 32.2747]

In[72]:= a[[1]] = 123.456
Out[72]= 123.456

In[75]:= a
Out[75]= {123.456, 29.1169, 6.5531, 19.6119, 38.5822, 44.8829, 38.5822, 32.2747}

Noch ein Mix! Man muss abwägen, ob die möglichen Fehler beim Indexshift nach C/C++ mehr Zeit kosten als die Tatsache, dass Mma. mit einem partiell (sprich - in letzter Konsequenz - fehlerhaft) überschriebenen Part[] Operator ausserordentlichen Unsinn (junk in, junk out) anfertigen kann.

Gruss
Udo.


Jens-Peer Kuska wrote:

Hallo,

also die Bemerkung "fast keine Zeit verbraucht" is ja wohl
ein Witz, man probiere

SetAttributes[myPart, HoldFirst]
myPart[a_, i_Integer] := a[[i + 1]]
SetAttributes[udoPart, HoldFirst]
udoPart[a_, i_Integer] := First[RotateLeft[a, i]]
Timing[
Table[
 k = Random[Integer, {0, Length[test] - 1}];
 myPart[test, k], {100000}
]
] // First
im Gegensatz zu
Timing[
Table[
 k = Random[Integer, {0, Length[test] - 1}];
 udoPart[test, k], {100000}
]
] // First

das Erste dauer bei mir 1.266 Sekunden, die Version mit RotateLeft[] is nach unglaublichen 144.14 Sekunden fertig.

Gruß
 Jens

----- Original Message ----- From: "Nowak Robert" <robert.nowak@XXXXXXX.at> To: "Udo und Susanne Krause" <su.krause@XXXXXXX.ch>; "Jens-Peer Kuska" <kuska@XXXXXXX.de> Cc: "Richard Gollreiter" <RGollreiter@XXXXXXX.de>; <demug@XXXXXXX.ch>
Sent: Monday, March 13, 2006 12:05 PM
Subject: RE: Antwort: Re: Indizierung von Tables mit Null beginnen.


| hallo udo,
|
| > Part /: Part[x_List, n_Integer] := First[RotateLeft[x, n]]
|
| wie funktioniert deine lösung eigentlich, wieso wird für das rotieren scheinbar keine zeit verbraucht ? | wird das array nur ein einziges mal rotiert und bei den individuellen zugriffen nicht mehr wenn ja, wodurch ?
|
| l.g. robert
|





Verweise:
Frühere   Chronologischer Index   Spätere
Vorherige   Thematischer Index   Nächste

DMUG DMUG-Archiv, http://www.mathematica.ch/archiv.html