Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

For example, I want to get an array with values sin(1),sin(2),..,sin(100) and store it to an variable. Is there a way to get this result by using foreach ?

EDIT: A more complicated example: Drawing 100 random points {(1,rnd),(2,rnd),...,(10,rnd)} and then drawing the distances from these points to their mean value.

I have no idea how to implements it in tikz, here is the pseudocode:

yarray = {}   //an array to store 100 random value
sum    = 0
for i = {1...100}
   yarray[i] = random
   sum = sum + yarray[i]
mean = sum/100
absarray = {}  //an array to store the distance from points to mean
for i = {1...100}
   absarray[i] = abs(yarray[i]-mean)

// draw the image
for i = {1...100}
   \fill (i,yarray[i]) circle (2pt)
   \fill (i,absarray[i]) circle (2pt)
share|improve this question
    
Welcome to TeX.SE. What kind of function is f? It would be very helpful if you composes a fully compilable [MWE](meta.tex.stackexchange.com/questions/228/… including the \documentclass and then those trying to help know for sure what you mean. –  Peter Grill Oct 7 '12 at 4:32
    
Is it always the case that the indices run over the positive integers? –  percusse Oct 7 '12 at 12:09

3 Answers 3

up vote 6 down vote accepted

Here is a way.

\documentclass{article}
\usepackage{tikz}

\makeatletter
\newcommand\store[6][\x]{%
  % #1 = dummy variable
  % #2 = variable to store the list
  % #3 = expression
  % #4 = expression to store (with \pgfmathresult) and possibly #1
  % #5 = start point
  % #6 = end point
  \gdef\store@temp{\@gobble}%
  \foreach #1 in {#5,...,#6}{\pgfmathparse{#3}\xdef\store@temp{\store@temp,#4}}%
  \let#2=\store@temp
}
\makeatother

\begin{document}

\store{\sineslist}{sin(deg(\x))}{\pgfmathresult}{1}{100}

\show\sineslist

\store[\i]{\randlist}{rand}{(\i,\pgfmathresult)}{1}{20}

\show\randlist

\end{document}

Here's what's reported:

> \sineslist=macro:
->0.84143,0.90924,0.14111,-0.75677,-0.95886,-0.27939,0.65697,0.9893,0.41208,-0.
544,-0.99995,-0.53654,0.42015,0.99057,0.65025,-0.28787,-0.96138,-0.75095,0.1498
6,0.91292,0.83662,-0.00885,-0.84619,-0.90555,-0.13234,0.76251,0.95636,0.27087,-
0.6636,-0.988,-0.40402,0.55139,0.99988,0.52907,-0.42815,-0.99173,-0.64352,0.296
34,0.96375,0.74509,-0.1586,-0.91647,-0.83174,0.01768,0.85086,0.90175,0.12357,-0
.7682,-0.9537,-0.26234,0.67021,0.98657,0.3959,-0.55878,-0.99971,-0.52153,0.4361
4,0.99284,0.6367,-0.30478,-0.9661,-0.73914,0.16733,0.92,0.8268,-0.02654,-0.8554
7,-0.8979,-0.11476,0.77385,0.95105,0.2538,-0.67673,-0.98512,-0.38777,0.56606,0.
99948,0.51398,-0.44408,-0.99385,-0.62988,0.3132,0.9683,0.73317,-0.17606,-0.9234
,-0.82178,0.03539,0.86002,0.89395,0.10597,-0.77942,-0.94824,-0.24522,0.68324,0.
98354,0.3796,-0.57335,-0.99916,-0.50635.

> \randlist=macro:
->(1,-0.86513),(2,-0.8214),(3,0.83136),(4,0.03825),(5,0.0602),(6,0.65846),(7,-0
.7918),(8,0.8938),(9,-0.13474),(10,-0.90755),(11,0.68077),(12,-0.1404),(13,-0.4
3602),(14,-0.08235),(15,0.65369),(16,-0.25284),(17,0.98817),(18,-0.09077),(19,0
.42735),(20,0.88712).
share|improve this answer

Unfortunately, I don't know how to deal with expansion related issues so can't give you the simple solution (attempt is commented out in). However, I have learned that using the datatool package works great for me:

enter image description here

Notes:

  • I manually stepped thru the DB rather than use \DTLdisplaydb so that you can see how to step thru it (amusing that you need the individual entries).
  • The expansion experets here can show you how to to expand the result to store, but below I attemped to use one of the solutions from How keep a running list of strings and then process them one at a time to keep the list of sin values.

Code:

\documentclass{article}
\usepackage{tikz}
\usepackage{datatool}


%% http://tex.stackexchange.com/questions/14393/how-keep-a-running-list-of-strings-and-then-process-them-one-at-a-time
%\def\ListOfValues{}
%\makeatletter
%\newcommand{\AddToListOfValues}[1]{%
%    \g@addto@macro\ListOfValues{{#1}}%
%}
%\makeatother

\begin{document}
\DTLnewdb{TableOfSinValues}
\foreach \x in {1,...,10} {%
    \pgfmathparse{sin(deg(\x))}
    %\edef\temp\pgfmathresult
    %\AddToListOfValues{\temp}%
    \DTLnewrow{TableOfSinValues}
    \dtlexpandnewvalue
    \DTLnewdbentry{TableOfSinValues}{Degree}{\x}
    \DTLnewdbentry{TableOfSinValues}{SinValue}{\pgfmathresult}
}%

List of $\sin$ Values:\bigskip

%\DTLdisplaydb{TableOfSinValues}% for automated display
\begin{tabular}{cr}
$x$ [degrees] & $\sin{x}$ \\[0.5ex]
\DTLforeach{TableOfSinValues}{\Degree=Degree, \SinValue=SinValue}{%
    $\Degree$ & $\SinValue$\\
}%
\end{tabular}
\end{document}
share|improve this answer

I have to say that I didn't get the distance argument in your question. I would not go with PGF or TikZ but produce data arrays stored in a file. That way you can access to the pgfplotstable and its quite fast macros. The TikZ part chokes in about 150 but the latter example goes pretty far (one other reason of course my code is not optimized at all so it's not only TikZ' fault).

Here is an example with 100 sample points drawn just with storing into arrays and reading them later and also a PGFPLOTSTABLE example I have compiled from the manual + some tweaks.

\documentclass{article}
\usepackage{pgfplotstable,booktabs}

%\pgfmathsetseed{226584}

\def\sample{100}
\pgfmathsetmacro{\runningrandarray}{rand} % Initial
\edef\runningmean{\runningrandarray}

\foreach \x[count=\xi from 1] in {2,...,\sample}{
\let\temprand\runningrandarray
\pgfmathsetmacro\tempres{rand}
\xdef\runningrandarray{\temprand,\tempres}
\pgfmathparse{(\xi*\runningmean+\tempres)/\x}
\xdef\runningmean{\pgfmathresult}
}
\xdef\randarray{{\runningrandarray}} % Double brace needed if you want to access via TikZ

\begin{document}
Some random points here : 

\begin{tikzpicture}
\foreach \x in {0,...,\number\numexpr\sample-1\relax}{
\pgfmathsetmacro\ycoord{\randarray[\x]}
    \node[circle,inner sep=1pt,fill=red,ultra thin] at (\x mm,\ycoord mm){};
    }
\end{tikzpicture}

and their current mean value is \runningmean

Instead we can directly go with PGFPLOTSTABLE package to produce the values: 

\pgfplotstablenew[
create on use/y/.style={create col/expr={\pgfplotstablerow+1}},
% define how the 'sine' column shall be filled:
create on use/sine/.style={create col/expr={sin(\pgfplotstablerow+1)}},
columns={y,sine}]{130}\loadedtable

\vspace{1cm}
\begin{minipage}[t]{0.58\textwidth}
show it as a table (columns skipped):
\centering
\pgfplotstabletypeset[
every head row/.style={before row=\toprule,after row=\midrule},
every last row/.style={after row=\bottomrule},
row predicate/.code={%
\ifnum#1>5\relax
\ifnum#1<125\relax
\pgfplotstableuserowfalse
\fi
\fi}
]
\loadedtable
\end{minipage}
\begin{minipage}[t]{0.4\textwidth}
or directly use it in plots

\begin{tikzpicture}
    \begin{axis}[width=4cm,height=7cm,xlabel={angle [deg]}]
    \addplot[no marks] table[x=y,y=sine]\loadedtable;
    \end{axis}
\end{tikzpicture}
\end{minipage}
\end{document}

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.