2

int generator

I currently generate deterministic pseudo-random ints using this code:

#include <chrono>
#include <ctime>
#include <random>
#include <stdint.h>

const uint32_t CurrentTime = static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now().time_since_epoch()).count());

std::mt19937 Mersenne = std::mt19937(static_cast<std::mt19937::result_type>(CurrentTime));

int Min = 3;
int Max = 6;
std::uniform_int_distribution<> Distribution(Min, Max-1);

int Result = Distribution(Mersenne);

The problem

There's two problems with this:

  1. The parameters for Distribution must be ints.
  2. The result from Distribution(Mersenne) is an int.

The question

How do I generate a random long long instead of an int, with the Min and Max parameters also being long longs instead of ints?

The context

I'm creating a deterministic game (peer-to-peer architecture), and the large minimum-size of a long long is needed as a sort of fixed-point number (since floats can cause non-determinism).

I won't accept answers that:

  • Use floats or doubles
  • Suggest generating an int and casting it to a long long
  • Generate random numbers non-deterministically (i.e. mersenne is deterministic if the same seed is used)

I would much prefer a solution from the standard library if there is one.

Ideally, the solution should be at least as efficient as my existing code on a 64-bit machine.

0liveradam8
  • 752
  • 4
  • 18
  • 6
    `std::uniform_int_distribution` ? Or am I missing something? – bolov Feb 09 '21 at 15:07
  • 1
    Just check the documentation of the constructor https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution/uniform_int_distribution, it clearly says that it uses the member type which can be any int type. – mediocrevegetable1 Feb 09 '21 at 15:09
  • 2
    @bolov shouldn't it be `std::uniform_int_distribution`? – Wyck Feb 09 '21 at 15:16
  • The question is valid, I don't understand the down vote – Adrian Maire Feb 09 '21 at 15:16
  • The source I got the code from didn't specify a template parameter for `std::uniform_int_distribution<> ` (this is even the case with the example code on [cppreference](https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution)). I didn't even think about what the `<>` was for. – 0liveradam8 Feb 09 '21 at 15:28
  • @Wyck the only legitimate use for `long long` is when you need to overload/specialize for all integer types. Else use `int` or `intN_t` or any of other integer aliases defined in `cstdint` – bolov Feb 09 '21 at 16:33

2 Answers2

6

the documentation says that the template parameter can be long long

long long Min = 3;
long long Max = 6;
std::uniform_int_distribution<long long> Distribution(Min, Max-1);

long long Result = Distribution(Mersenne);
prog-fh
  • 13,492
  • 1
  • 15
  • 30
1

Would that work for you?

#include <climits>
#include <random>
#include <iostream>

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd()); // Here you can use any seed to make it deterministic
    std::uniform_int_distribution<long long> distrib(LLONG_MIN, LLONG_MAX);
    
    for (int n = 0; n < 5; ++n)
        std::cout << distrib(gen) << ' ';
    
    std::cout << '\n';
}
no one special
  • 1,608
  • 13
  • 32