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
|