1

For testing I need reproducible random numbers. The randomness isn't that important. Currently I'm setting a seed std::srand(x) and use std::rand() to generate. As expected the numbers are always the same on multiple runs with the same seed.

For some other parts I need UUIDs. I use the utils-linux libuuuid.

But running this code:

  std::srand(2);

  uuid_t uuid;
  
  int x = std::rand();
  uuid_generate(uuid);
  int y = std::rand();

y is different on every run.

I already tried to use uuid_generate_time,uuid_generate_time_safe but this doesn't generate fully random UUIDs on multiple calls:

d4e25820-92ca-11eb-9b39-f91e898522ad
d4e25821-92ca-11eb-9b39-f91e898522ad
d4e25822-92ca-11eb-9b39-f91e898522ad
d4e25823-92ca-11eb-9b39-f91e898522ad

Is there any other way I could implement this?

Jarvum
  • 76
  • 1
  • 7
  • 1
    Do you want the same UUID:s - or why do you care about what `rand()` returns? Do you want a PRNG that is totally unaffected by `uuid_generate`? If so, use one of the generators in ``, like `std::mt19937`. – Ted Lyngmo Apr 01 '21 at 10:59
  • Yes, the rand() result should be unaffected (or at least all the same after the uuid_generate call). For testing it would also be nice to have same UUIDs but this isn't important. I though that rand() does use its own pseudo-random-generator after seeding and uuid_generate (in my current setup) /dev/urandom. I'll try out the generators. – Jarvum Apr 01 '21 at 11:18
  • If high-quality randomness from `/dev/urandom` is available, your seed won't matter. In that case, `uuid_generate` will pick random numbers from an entropy pool. – Ted Lyngmo Apr 01 '21 at 11:21

1 Answers1

2

As expected the numbers are always the same on multiple runs with the same seed.

Until they are not. rand() is not required to use a certain algorithm. It can change if you upgrade - or if you compile on a different platform.

It may also be affected by other functions as you've noticed.

You could use a generator from <random> instead. Every instance of such a generator will be totally unaffected by other functions that you call.

#include <uuid/uuid.h>

#include <iostream>
#include <random> // std::mt19937, std::uniform_int_distribution

auto& prng() {
    // Create a static seeded PRNG to use everywhere in the program
    // thread_local std::mt19937 instance(std::random_device{}());

    // A PRNG with hardcoded seed for testing:
    thread_local std::mt19937 instance(2);
    return instance;
}

int main() {
    uuid_t uuid;
    std::uniform_int_distribution<int> dist(0, 10000);

    int x = dist(prng());
    uuid_generate(uuid);
    int y = dist(prng());
    std::cout << x << '\n' << y << '\n'; // 4360 and 1851 - everywhere
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108