Creating Random Values in Zig 0.16.0

Creating Random Values in Zig 0.16.0 Link to heading

Generating random numbers and values is a common task in systems programming, whether for simulations, testing, cryptography, or games. The original article demonstrated random value generation using Zig 0.15.1 and the std.crypto.random API. With the release of Zig 0.16.0, the standard library introduced a major overhaul of the I/O subsystem. As a result, std.crypto.random is no longer directly available as a global std.Random interface. All randomness is now accessed through an std.Io context, providing better integration with async code, cancellation and platform-specific entropy sources.

This updated guide shows the recommended way to create both cryptographically secure random values and deterministic pseudo-random values in Zig 0.16.0.

Here is a complete, self-contained example using the new APIs:

const std = @import("std");

pub fn main(init: std.process.Init) !void {
    const io = init.io;

    // Create a std.Random interface backed by the I/O context
    const rng_impl: std.Random.IoSource = .{ .io = io };
    const secureRand = rng_impl.interface();

    std.debug.print("Random u8: {}\n", .{secureRand.int(u8)});
    std.debug.print("Random u8 less than 10: {}\n", .{secureRand.uintLessThan(u8, 10)});
    std.debug.print("Random u16: {}\n", .{secureRand.int(u16)});
    std.debug.print("Random u32: {}\n", .{secureRand.int(u32)});
    std.debug.print("Random i32: {}\n", .{secureRand.int(i32)});
    std.debug.print("Random float: {d}\n", .{secureRand.float(f64)});

    var data = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50 };
    std.Random.shuffle(secureRand, u8, &data);
    std.debug.print("Shuffled data: {any}\n", .{data});

    // Pseudo-random number generator (PRNG) – deterministic and seedable
    var prng = std.Random.DefaultPrng.init(0);
    const rand = prng.random();

    const a = rand.float(f32);
    std.debug.print("Random float: {d}\n", .{a});

    const b = rand.boolean();
    std.debug.print("Random boolean: {}\n", .{b});

    const c = rand.int(u8);
    std.debug.print("Random u8: {}\n", .{c});

    const d = rand.intRangeAtMost(u8, 0, 255);
    std.debug.print("Random u8: {}\n", .{d});
}

Save the code as randomValues.zig and execute it:

$ zig version
0.16.0
$ zig run randomValues.zig
Random u8: 125
Random u8 less than 10: 5
Random u16: 50160
Random u32: 2327231673
Random i32: -1486369972
Random float: 0.25350436671474214
Shuffled data: { 6, 50, 2, 20, 8, 40, 5, 9, 3, 1, 7, 30, 10, 4 }
Random float: 0.27175805
Random boolean: true
Random u8: 252
Random u8: 26

Happy coding in Zig!