Commit 1d5ea10bee

Erik Arvstedt <erik.arvstedt@gmail.com>
2022-05-12 14:13:20
std.rand: fixup 'improve random float generation'
- Test: Fix bucket counting. Previously, the first hit was not counted. This off-by-one error slightly increased the mean of `*_total_variance`, which decreased the acceptance rate for a particular random seed from 95% to 92.6%. (Irrelevant for test failure because the seed is fixed.) - Improve comments
1 parent 7bedeb9
Changed files (2)
lib
lib/std/rand/test.zig
@@ -336,13 +336,13 @@ test "Random float chi-square goodness of fit" {
         if (f32_put.found_existing) {
             f32_put.value_ptr.* += 1;
         } else {
-            f32_put.value_ptr.* = 0;
+            f32_put.value_ptr.* = 1;
         }
         var f64_put = try f64_hist.getOrPut(@floatToInt(u32, rand_f64 * @intToFloat(f64, num_buckets)));
         if (f64_put.found_existing) {
             f64_put.value_ptr.* += 1;
         } else {
-            f64_put.value_ptr.* = 0;
+            f64_put.value_ptr.* = 1;
         }
     }
 
@@ -371,7 +371,7 @@ test "Random float chi-square goodness of fit" {
         }
     }
 
-    // Corresponds to a p-value > 0.05.
+    // Accept p-values >= 0.05.
     // Critical value is calculated by opening a Python interpreter and running:
     // scipy.stats.chi2.isf(0.05, num_buckets - 1)
     const critical_value = 1073.6426506574246;
lib/std/rand.zig
@@ -247,10 +247,9 @@ pub const Random = struct {
 
     /// Return a floating point value evenly distributed in the range [0, 1).
     pub fn float(r: Random, comptime T: type) T {
-        // Generate a uniformly random value between for the mantissa.
+        // Generate a uniformly random value for the mantissa.
         // Then generate an exponentially biased random value for the exponent.
-        // Over the previous method, this has the advantage of being able to
-        // represent every possible value in the available range.
+        // This covers every possible value in the range.
         switch (T) {
             f32 => {
                 // Use 23 random bits for the mantissa, and the rest for the exponent.
@@ -259,6 +258,9 @@ pub const Random = struct {
                 const rand = r.int(u64);
                 var rand_lz = @clz(u64, rand | 0x7FFFFF);
                 if (rand_lz == 41) {
+                    // TODO: when #5177 or #489 is implemented,
+                    // tell the compiler it is unlikely (1/2^41) to reach this point.
+                    // (Same for the if branch and the f64 calculations below.)
                     rand_lz += @clz(u64, r.int(u64));
                     if (rand_lz == 41 + 64) {
                         // It is astronomically unlikely to reach this point.