Hi all,
I'm trying to implement a linear congruential pseudorandom number generator (<http://en.wikipedia.org/wiki/Linear\_congruential_generator>\), since $RANDOM and /dev/random aren't standardized. I'm referring to the Shell & Utilities volume of POSIX.1-2008, but I'm running into some odd issues. This works fine:
#! /bin/sh
rand_x=1
rand()
{
rand_x=$(((($rand_x * 1103515245) + 12345) % 4294967296))
echo $rand_x
}
while true; do
rand
sleep 2
done
But I want to use the generated integer in an arithmetic expansion, for modular arithmetic (I know it's a sloppy way of limiting the range of values, but it's good enough for my purpose).
I've tried the following, but it simply repeats "1103527590 0" over and over:
#! /bin/sh
rand_x=1
rand()
{
rand_x=$(((($rand_x * 1103515245) + 12345) % 4294967296))
echo $rand_x
}
while true; do
r=`rand`
printf '%i %i\n' $r $(($r % 3))
sleep 2
done
Similarly, this repeats "1103527590":
#! /bin/sh
rand_x=1
rand()
{
rand_x=$(((($rand_x * 1103515245) + 12345) % 4294967296))
echo $rand_x
}
while true; do
printf '%i\n' `rand`
sleep 2
done
It looks like, if I try to store or use the output of rand(), either $rand_x is being reset to 1 each time or the arithmetic substitution in rand() isn't being used.
But if I access $rand_x directly, as in the following script, I get the correct sequence:
#! /bin/sh
rand_x=1
rand()
{
rand_x=$(((($rand_x * 1103515245) + 12345) % 4294967296))
}
while true; do
rand
printf '%i %i\n' $rand_x $(($rand_x % 3))
sleep 2
done
However I'd like to avoid exposing $rand_x like that (rand() will eventually become a library function). So does anyone have any idea why using echo and capturing/using the output of rand() isn't working?
I'm testing this in GNU Bash and dash on GNU/Linux. When I get this working, I'll test it in more shells.
---------- Post updated at 23:58 ---------- Previous update was at 23:26 ----------
The former seems to be the case. If I echo $rand_x from rand() and just store the output of rand(), $rand_x is reset to 1 for some reason.
The following script illustrates this:
#! /bin/sh
rand_x=1
rand()
{
rand_x=$(((($rand_x * 1103515245) + 12345) % 4294967296))
echo $rand_x >&2
echo $rand_x
}
while true; do
r=`rand`
printf '%i %i\n' $rand_x $(($rand_x % 3))
sleep 2
done
Note that in rand(), $rand_x is now also printed to standard error (file descriptor 2) so it appears on the terminal even though standard output is stored in $r.
Output (file descriptors 1 and 2):
Anyone have any idea why this is happening?