Creating Random Values in Zig
This blog post shows how to generate random numbers using the standard library. But first, here is the relevant code:
const std = @import("std");
const builtin = @import("builtin");
const print = std.debug.print;
pub fn main() !void {
const secureRand = std.crypto.random;
print("Random u8: {}\n", .{secureRand.int(u8)});
print("Random u8 less than 10: {}\n", .{secureRand.uintLessThan(u8, 10)});
print("Random u16: {}\n", .{secureRand.int(u16)});
print("Random u32: {}\n", .{secureRand.int(u32)});
print("Random i32: {}\n", .{secureRand.int(i32)});
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);
print("Shuffled data: {any}\n", .{data});
var prng = std.Random.DefaultPrng.init(0);
const rand = prng.random();
const a = rand.float(f32);
print("Random float: {d}\n", .{a});
const b = rand.boolean();
print("Random boolean: {}\n", .{b});
const c = rand.int(u8);
print("Random u8: {}\n", .{c});
const d = rand.intRangeAtMost(u8, 0, 255);
print("Random u8: {}\n", .{d});
}
This program demonstrates two primary methods for generating random data using the standard library. After importing std and aliasing std.debug.print as print, the main() function begins by accessing the system’s cryptographically secure random number generator (CSRNG) via std.crypto.random. It uses this secure source to generate and print random values of various types: standard integers (u8, u16, u32, i32), a bounded integer (a u8 less than 10 using uintLessThan), and a 64-bit float. This same secureRand instance is then used with std.Random.shuffle to randomize the order of elements in a locally defined byte array named data.
The program then contrasts this with a pseudo-random number generator (PRNG). It explicitly initializes an instance of std.Random.DefaultPrng with a fixed seed of 0, making its output deterministic and reproducible. From this prng state, it gets a std.Random interface named rand. This interface is then used to generate and print a 32-bit float, a random boolean (true or false), a full-range u8, and another u8 within the specific inclusive range of 0 to 255 using intRangeAtMost. The code successfully highlights the difference between using the system’s secure generator (ideal for cryptography or shuffling) and a seedable PRNG (useful for simulations or reproducible tests).
Save it as randomValues.zig and run it on your machine:
$ zig version
0.15.1
$ zig run randomValues.zig
Random u8: 100
Random u8 less than 10: 5
Random u16: 19501
Random u32: 3994165071
Random i32: -1192023224
Random float: 0.5550960713689771
Shuffled data: { 3, 6, 50, 7, 5, 4, 9, 8, 2, 40, 20, 10, 1, 30 }
Random float: 0.27175805
Random boolean: true
Random u8: 252
Random u8: 26
Happy coding in Zig!