9
$\begingroup$

Using Mathematica, I need to define a function of one integer variable that generates the same real number in the range 0 to 1, if it is called with the same argument, but gives a different real number if its argument is changed. For example :

Func[1] = 0.12675,
Func[2] = 0.11213,
Func[2] = 0.11213,
Func[1] = 0.12675,
Func[3] = 0.02561,

and so on.

How can I define such a function?

Edit

A more precise statement of the pseudo-random nature of the function Func.

The function should generate new numbers for each Mathematica session. So after thousands of sessions, the values Func[1] are uniformly distributed on the intervall 0 to 1. For a given session, Func[1] generates the same number again and again. But in the next session, Func[1] would be a different number. Otherwise, the generated numbers couldn't be considered as "random" if they are always the same.

$\endgroup$
4
  • $\begingroup$ Can give a precise definition of "random" here? Since the function is deterministic, this is a very relevant and non-trivial question. $\endgroup$
    – Szabolcs
    Commented Mar 8, 2013 at 2:13
  • $\begingroup$ I mean uniformly distributed real numbers in the interval 0 to 1. $\endgroup$
    – Cham
    Commented Mar 8, 2013 at 2:17
  • $\begingroup$ I'd still like to know what you need this for and why a pre-generated list of numbers won't do. $\endgroup$
    – Szabolcs
    Commented Mar 8, 2013 at 3:51
  • $\begingroup$ @Szabolcs, I'm trying to generate a random distribution of points in 3D space to simulate the Crab nebula, with its filaments structure. Currently, I'm still unable to generate the filaments, and the random function is an experiment to generate several small lines. There's probably a better way to do this, though. I may ask a question on this subject with another topic. $\endgroup$
    – Cham
    Commented Mar 8, 2013 at 4:38

3 Answers 3

11
$\begingroup$

This one will be the same in a single session. However, it will be different each time the kernel is (re)started, or if func is cleared and the definition re-executed.

func[x_] := func[x] = RandomReal[];

If you wish func to give the same values every time you run Mathematica, then you could use SeedRandom[1], or whatever seed appeals to you, in a session before func is used. The values will be the same provided func[x] is always evaluated in the same order for each x. (If the order cannot be guaranteed, then another answer will be better.)

Here is a related answer on the use of the above trick in similar circumstances, called memoization.

$\endgroup$
6
  • $\begingroup$ I was just going to post the same, +1. $\endgroup$
    – Szabolcs
    Commented Mar 8, 2013 at 2:39
  • $\begingroup$ @Szabolcs I was just pondering, is there any worry, if RandomReal is called elsewhere? Or if func[x] is called, with x in a constructed order, such that func[1], func[2], etc. would not be a random sequence? I can't figure out if that is possible. $\endgroup$
    – Michael E2
    Commented Mar 8, 2013 at 2:45
  • 2
    $\begingroup$ FWIW, this can be written more tersely as: m : func[x_] := m = RandomReal[]; $\endgroup$
    – Mr.Wizard
    Commented Mar 8, 2013 at 3:09
  • $\begingroup$ @Mr.Wizard Hey, that's cute. I hadn't seen that before. I wonder, though, if you think that's a good way to write it? It's terser, but the traditional(?) way seems easier to read. Well, it would since I'm used to it. $\endgroup$
    – Michael E2
    Commented Mar 8, 2013 at 3:24
  • $\begingroup$ Well, you know I love terse coding. In practice I often use mem : f[. . .] := mem = . . . as that is both terse and (IMHO) clear. This is assuming of course that it is for the purpose memoization and not something else. Using the Pattern is actually less prone to typos because you do not need to rewrite the entire function definition a second time. $\endgroup$
    – Mr.Wizard
    Commented Mar 8, 2013 at 3:33
3
$\begingroup$

You can simply create a big list of numbers, list = RandomReal[1, 1000000], and take those numbers one by one.

The elements of this list will be uniformly distributed and uncorrelated. I was assuming that this is what you meant by "random", which is the most important part of the question here. Perhaps you could clarify this.

$\endgroup$
4
  • $\begingroup$ Yes, I need uniformly distributed random numbers, in the interval 0 to 1. Apparently, the solution from belisarius : f[x_] := (SeedRandom[x]; RandomReal[]), is doing this, but I'm not sure yet. $\endgroup$
    – Cham
    Commented Mar 8, 2013 at 2:15
  • $\begingroup$ @Martin Uniformly distributed and "random" are not the same thing. Table[Mod[i, 10], {i, 10000000}] are uniformly distributed integers. Do you consider them random? $\endgroup$
    – Szabolcs
    Commented Mar 8, 2013 at 2:17
  • $\begingroup$ Hmm, then I'm not sure how to define "random" here. For all practical purposes, I need the function to generate any real number (in the interval 0 to 1) like the usual Random[Real, {0, 1}] command, but must give the same number again if I call the function with the same integer argument. $\endgroup$
    – Cham
    Commented Mar 8, 2013 at 2:22
  • $\begingroup$ I have to go with Szabolcs here. If the Mathematica developers have done their job right then this will do what the OP is asking for. If they haven't, the other approaches may not be curing that problem either (or may even be worse). $\endgroup$
    – sebhofer
    Commented Mar 8, 2013 at 9:16
2
$\begingroup$

I believe ...

f[x_] := (SeedRandom[x]; RandomReal[])
$\endgroup$
6
  • 2
    $\begingroup$ I expected something better from you :P There's no guarantee that these will be uniformly distributed or that they will be uncorrelated if you take Table[f[i], {i, bigNumber}]. But of course the question is what does the OP really mean by "random"? $\endgroup$
    – Szabolcs
    Commented Mar 8, 2013 at 2:08
  • $\begingroup$ @Szabolcs I needed to save a few chars just to beat Leonid :P $\endgroup$ Commented Mar 8, 2013 at 2:09
  • $\begingroup$ This solution appears to be working great. The numbers should be uniformly distributed in the interval 0 to 1 $\endgroup$
    – Cham
    Commented Mar 8, 2013 at 2:09
  • $\begingroup$ So I now have two solutions which apparently are working great for what I need to do : func1[x_] := func[x] = RandomReal[]; and func2[x_] := (SeedRandom[x]; RandomReal[]). Which one should I use ? Which is "better" (I know, this question may be stupid, but I'm asking it anyway!). $\endgroup$
    – Cham
    Commented Mar 8, 2013 at 2:39
  • 2
    $\begingroup$ @Szabolcs I just did a quick test for whiteness using Ljung-Box test (and another test using periodograms whos name I don't know) on a 50k sample created by this method and it looks good. (I did the test in Matlab so I can't post the code.) Didn't test for uniformity though. $\endgroup$
    – sebhofer
    Commented Mar 8, 2013 at 9:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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