Returns a random fractional number between 0 and the value of EXPR.
(EXPR should be positive.) If EXPR is omitted, returns a value between
-0 and 1. This function produces repeatable sequences unless srand()
-is invoked. See also srand().
+0 and 1. Automatically calls srand() unless srand() has already been
+called. See also srand().
(Note: if your rand function consistently returns numbers that are too
large or too small, then your version of Perl was probably compiled
=item srand EXPR
-Sets the random number seed for the C<rand> operator. If EXPR is omitted,
-uses a semi-random value based on the current time and process ID, among
-other things. In versions of Perl prior to 5.004 the default seed was
-just the current time(). This isn't a particularly good seed, so many
-old programs supply their own seed value (often C<time ^ $$> or C<time ^
-($$ + ($$ << 15))>), but that isn't necessary any more.
-
-You need something much more random than the default seed for
-cryptographic purposes, though. Checksumming the compressed output of
-one or more rapidly changing operating system status programs is the
-usual method. For example:
+=item srand
+
+Sets the random number seed for the C<rand> operator. If EXPR is
+omitted, uses a semi-random value based on the current time and process
+ID, among other things. In versions of Perl prior to 5.004 the default
+seed was just the current time(). This isn't a particularly good seed,
+so many old programs supply their own seed value (often C<time ^ $$> or
+C<time ^ ($$ + ($$ << 15))>), but that isn't necessary any more.
+
+In fact, it's usually not necessary to call srand() at all, because if
+it is not called explicitly, it is called implicitly at the first use of
+the C<rand> operator.
+
+However, you need something much more random than the default seed for
+cryptographic purposes. Checksumming the compressed output of one or
+more rapidly changing operating system status programs is the usual
+method. For example:
srand (time ^ $$ ^ unpack "%L*", `ps axww | gzip`);
typedef int IBW;
typedef unsigned UBW;
-static SV* refto _((SV* sv));
static void doencodes _((SV* sv, char* s, I32 len));
+static SV* refto _((SV* sv));
+static U32 seed _((void));
+
+static bool srand_called = FALSE;
/* variations on pp_null */
value = POPn;
if (value == 0.0)
value = 1.0;
+ if (!srand_called) {
+ (void)srand((unsigned)seed());
+ srand_called = TRUE;
+ }
#if RANDBITS == 31
value = rand() * value / 2147483648.0;
#else
PP(pp_srand)
{
dSP;
- I32 anum;
+ UV anum;
+ if (MAXARG < 1)
+ anum = seed();
+ else
+ anum = POPu;
+ (void)srand((unsigned)anum);
+ srand_called = TRUE;
+ EXTEND(SP, 1);
+ RETPUSHYES;
+}
- if (MAXARG < 1) {
+static U32
+seed()
+{
+ U32 u;
#ifdef VMS
# include <starlet.h>
- unsigned int when[2];
- _ckvmssts(sys$gettim(when));
- anum = when[0] ^ when[1];
+ unsigned int when[2];
+ _ckvmssts(sys$gettim(when));
+ u = when[0] ^ when[1];
#else
# ifdef HAS_GETTIMEOFDAY
- struct timeval when;
- gettimeofday(&when,(struct timezone *) 0);
- anum = when.tv_sec ^ when.tv_usec;
+ struct timeval when;
+ gettimeofday(&when,(struct timezone *) 0);
+ u = when.tv_sec ^ when.tv_usec;
# else
- Time_t when;
- (void)time(&when);
- anum = when;
+ Time_t when;
+ (void)time(&when);
+ u = when;
# endif
#endif
-#if !defined(PLAN9) /* XXX Plan9 assembler chokes on this; fix coming soon */
- /* 17-Jul-1996 bailey@genetics.upenn.edu */
- /* What is a good hashing algorithm here? */
- anum ^= ( ( 269 * (U32)getpid())
- ^ (26107 * (U32)&when)
- ^ (73819 * (U32)stack_sp));
+#ifndef PLAN9 /* XXX Plan9 assembler chokes on this; fix needed */
+ /* What is a good hashing algorithm here? */
+ u ^= ( ( 269 * (U32)getpid())
+ ^ (26107 * (U32)&when)
+ ^ (73819 * (U32)stack_sp));
#endif
- }
- else
- anum = POPi;
- (void)srand(anum);
- EXTEND(SP, 1);
- RETPUSHYES;
+ return u;
}
PP(pp_exp)