Improving Float.random(in:using:)

OK, I've added that fix to my copy and done some more testing.

I think there are two more issues, for ranges that span from neg to pos:

  • It returns both -0 and +0, as if they were separate values, leading to zero being twice as probable as it should be.

  • It will never return the lowest value(s).


Unless there's something wrong with my Float8 implementation.

I have this program:

func test2() {
    var prng = WyRand()
    let range = -Float8(0.25) ... Float8(0.25)
    var hist = [UInt8 : UInt64]()
    for _ in 0 ..< 1024*1024*16 {
        let f = Float8.uniformRandom(in: range, using: &prng)
        precondition(f >= range.lowerBound)
        precondition(f <= range.upperBound)
        hist[f.bitPattern, default: 0] &+= 1
    }
    for (v, c) in hist
        .map( { (k, v) in (Float8(bitPattern: k), v) })
        .sorted(by: { $0.0 < $1.0 })
    {
        print(v.leftPadded(to: 12), c.leftPadded(to: 12))
    }
}

which prints:

    -0.21875       508187
   -0.203125       509107
     -0.1875       508170
   -0.171875       508190
    -0.15625       509122
   -0.140625       506923
      -0.125       508131
  -0.1171875       254522
   -0.109375       254622
  -0.1015625       253875
    -0.09375       254150
  -0.0859375       254467
   -0.078125       255003
  -0.0703125       254489
     -0.0625       253645
 -0.05859375       126968
  -0.0546875       126530
 -0.05078125       127365
   -0.046875       127228
 -0.04296875       126859
  -0.0390625       127214
 -0.03515625       126985
    -0.03125       127250
-0.029296875        63996
 -0.02734375        63541
-0.025390625        63285
  -0.0234375        64074
-0.021484375        63689
 -0.01953125        63317
-0.017578125        63752
   -0.015625        63303
-0.013671875        63612
 -0.01171875        63768
-0.009765625        63651
  -0.0078125        63658
-0.005859375        63417
 -0.00390625        63388
-0.001953125        63283
         0.0        63822
        -0.0        63690
 0.001953125        63852
  0.00390625        63022
 0.005859375        63883
   0.0078125        63613
 0.009765625        63336
  0.01171875        63880
 0.013671875        63492
    0.015625        63690
 0.017578125        63412
  0.01953125        63818
 0.021484375        63175
   0.0234375        64183
 0.025390625        63378
  0.02734375        63788
 0.029296875        63606
     0.03125       127193
  0.03515625       126783
   0.0390625       126845
  0.04296875       127229
    0.046875       127361
  0.05078125       127118
   0.0546875       126800
  0.05859375       127299
      0.0625       254559
   0.0703125       254697
    0.078125       253568
   0.0859375       254446
     0.09375       253203
   0.1015625       253773
    0.109375       254352
   0.1171875       254890
       0.125       508204
    0.140625       507725
     0.15625       509499
    0.171875       509270
      0.1875       508547
    0.203125       508257
     0.21875       508844
    0.234375       507503
        0.25      1014875

Note that the expected first two values -0.25 and -0.234375 are missing, and that both -0 and 0 are there as separate values.