Use of Random

I am afraid the std.Random.zig is unreadable for me. No useful comments provided. Strange anytype pointers..
How can I generate some random numbers 0 <= r <= 9?

const std = @import("std");

pub fn main() !void {
    // userland rng implementation
    var prng = std.Random.DefaultPrng.init(seed: {
        var seed: u64 = undefined;
        // get random seed from OS
        try std.posix.getrandom(std.mem.asBytes(&seed));
        break :seed seed;
    });
    // get interface
    const rand = prng.random();
    const n = rand.intRangeAtMost(u8, 0, 9);
    std.debug.print("{}", .{n});
}
4 Likes

Some Alternatives

  • Use crypto to generate the seed:
const seed = std.crypto.random.int(u64);
var prng = std.Random.DefaultPrng.init(seed);
const rand = prng.random();
_ = rand.uintAtMost(u4, 9);
  • When testing there is std.testing.random_seed:
var prng = std.Random.DefaultPrng.init(std.testing.random_seed);
const rand = prng.random();
_ = rand.uintAtMost(u4, 9);

Note that prng must be var to hold the random generator state.

11 Likes

Thanks!
Writing Zig is easier then reading.

We also have PRNG module in TigerBeetle:

This is mostly to avoid stdlib churn, but I also cleaned up the API to my taste somewhat (e.g.), and we have a second fun implementation of the same API here (and a third one, finite rng, is on my todo list…)

3 Likes

Heyo, sorry for having to bring this back from the dead, but with Zig being an extremely fast-changing language (which is a good thing, don’t get me wrong), sometimes solutions become outdated.

I’ve been trying to achieve the same goal for a while today: Generate a random number min < n < max

I’ve managed to figure out (vial trial and error… :sweat_smile: ) how to get me a Random that I can use, but I fail to find a proper way of seeding it.

Here’s why I can’t get a proper seed value:

  1. std.posix does not contain the getrandom member (anymore?)
  2. std.crypto does not contain the random member anymore
  3. all timestamp functions in std.Io.Clock return signed integers, while the Random expects a u64

So really, it’s about getting a proper u64 seed for my random, either form a timestamp or from system entropy, but I haven’t figured out either so far, and asking the (awesome!) community is my best bet right now.

Hope y’all can help! Maybe I’m just missing something extremely obvious…

if you have 64 bits of something from std.Io.Clock, why not @bitCast to get a u64?

1 Like

Tried that just now, maybe I did something wrong but I’m getting:

error: cannot @bitCast from ‘Io.Timestamp’; struct does not have a guaranteed in-memory layout

I also remember trying @intCast but that was futile (I’ very recently picked up Zig, and despite having lots of previous experience especially in C and partially C++ it’s some new stuff for me)

Nvm I’m an idiot I tried to cast the Timestamp. Actually using the toSeconds or toMicroseconds functions does exactly what it should do.

2 Likes