まつもと ゆきひろです

In message "[ruby-dev:2620] Re: experimental release 1.1b9_18"
    on 98/05/14, WATANABE Hirofumi <watanabe / ase.ptg.sony.co.jp> writes:

|わたなべです.

|1. random() を使うのやめて rand() にする.
|2. random() を 1000 回くりかえして最大値を求め, そこからほん
|   との最大値を推測する configure を書く. perl の Configure
|   こんな感じ. random() じゃなくて rand() だけど.

randとrandomでは明らかに乱数の性質が違う(randomの方が良い)ら
しいので,1はちょっと避けた方が良いように思います.では,2を
するしかないか,と思っていたのですが,algaeというソフトの乱
数ルーチンを参考に書き換えてみました.

# これはrandomのmaxを2^31-1に仮定してるけど….

こっちはより性質の良いと言うdrand48を使ってますし,けっこう
いけるのではないかと思います.試してみて下さい.

# ついでにrand(0)で0から1までの実数を返すようにしました.
# これは実験的な仕様です.

パッチは以下の通り.

diff -w -u -1 -r1.1.1.2.2.5 random.c
--- random.c	1998/05/13 05:58:05	1.1.1.2.2.5
+++ random.c	1998/05/14 04:57:32
@@ -30,2 +30,47 @@
 
+/*
+ * Prefer to use drand48, otherwise use random, or rand as a last resort.
+ */
+#ifdef HAVE_DRAND48
+
+#ifndef HAVE_DRAND48_DECL
+double drand48 _((void));
+void srand48 _((long));
+#endif
+
+#define SRANDOM(s)	srand48((long)(s))
+#define RANDOM_NUMBER	drand48()
+
+#else /* not HAVE_DRAND48 */
+
+/*
+ * The largest number returned by the random number generator is
+ * RANDOM_MAX.  If we're using `rand' it's RAND_MAX, but if we're
+ * using `random' it's 2^31-1.
+ */
+#ifndef RANDOM_MAX
+# ifndef HAVE_RANDOM
+#  define RANDOM_MAX	RAND_MAX
+# else
+#  define RANDOM_MAX	2147483647.0
+# endif
+#endif
+
+#ifdef HAVE_RANDOM
+
+#define RANDOM	random
+#define SRANDOM	srandom
+
+#else /* HAVE_RANDOM */
+
+#define RANDOM	rand
+#define SRANDOM	srand
+
+#endif /* HAVE_RANDOM */
+
+/* 0 <= RANDOM_NUMBER <= 1 */
+#define RANDOM_NUMBER (((double)RANDOM())/(double)RANDOM_MAX)
+
+#endif /* not HAVE_DRAND48 */
+
 #ifdef HAVE_RANDOM
@@ -63,10 +108,5 @@
     }
-
-    srandom(seed);
-    old = saved_seed;
-    saved_seed = seed;
+#endif
 
-    return int2inum(old);
-#else
-    srand(seed);
+    SRANDOM(seed);
     old = saved_seed;
@@ -75,3 +115,2 @@
     return int2inum(old);
-#endif
 }
@@ -95,14 +134,6 @@
     max = NUM2INT(vmax);
-    if (max == 0) ArgError("rand(0)");
-
-#ifdef HAVE_RANDOM
-    val = random();
-#else
-    val = rand();
-#endif
-#ifdef RAND_MAX
-    val = val * (double)max / (double)RAND_MAX;
-#else
-    val = (val>>8) % max;
-#endif
+    if (max == 0) {
+	return float_new(RANDOM_NUMBER);
+    }
+    val = max*RANDOM_NUMBER;