From f33363c6b8fd7c3843efc9772f7e296ba07ff189 Mon Sep 17 00:00:00 2001 From: B1Z0N Date: Thu, 22 Aug 2019 15:47:05 +0300 Subject: [PATCH 1/5] Updated big_random function to use mersenne twister --- include/functions/random.hpp | 40 ++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/include/functions/random.hpp b/include/functions/random.hpp index 10d08cc..82cf8e3 100644 --- a/include/functions/random.hpp +++ b/include/functions/random.hpp @@ -24,25 +24,39 @@ const size_t MAX_RANDOM_LENGTH = 1000; */ BigInt big_random(size_t num_digits = 0) { - std::random_device rand_generator; // true random number generator - - if (num_digits == 0) // the number of digits were not specified + /** + * This generators needed to be created only once, + * because properly seeded std::mt19937 can generate + * 2^19937 - 1 potential states which is more than + * enough for most usecases + */ + + // seed sequence, seeded with true random generator + // used for better entropy + static std::seed_seq sseq{std::random_device{}()}; + // generator itself + static std::mt19937 gen{sseq}; + static std::uniform_int_distribution<> digit_distr(0, 9); + static std::uniform_int_distribution<> first_digit_distr(-9, 9); + // number to generate + static BigInt big_rand; + + if (num_digits == 0) { + // the number of digits were not specified // use a random number for it: - num_digits = 1 + rand_generator() % MAX_RANDOM_LENGTH; - - BigInt big_rand; - big_rand.value = ""; // clear value to append digits + num_digits = 1 + gen() % MAX_RANDOM_LENGTH; + } - // ensure that the first digit is non-zero - big_rand.value += std::to_string(1 + rand_generator() % 9); + // first digit and sign + auto first_digit = first_digit_distr(gen); + big_rand.value = std::to_string(abs(first_digit)); + big_rand.sign = first_digit < 0 ? '-' : '+'; + // insert other digits while (big_rand.value.size() < num_digits) - big_rand.value += std::to_string(rand_generator()); - if (big_rand.value.size() != num_digits) - big_rand.value.erase(num_digits); // erase extra digits + big_rand.value += std::to_string(digit_distr(gen)); return big_rand; } - #endif // BIG_INT_RANDOM_FUNCTIONS_HPP From 4932e30188d7ae12df1b34bda612b8d526cd648c Mon Sep 17 00:00:00 2001 From: B1Z0N Date: Thu, 22 Aug 2019 15:48:12 +0300 Subject: [PATCH 2/5] Updated big_random tests to support new version of this function --- test/functions/random.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/functions/random.cpp b/test/functions/random.cpp index 3d7b113..e6d50ae 100644 --- a/test/functions/random.cpp +++ b/test/functions/random.cpp @@ -5,6 +5,10 @@ #include "functions/random.hpp" #include "operators/io_stream.hpp" +// for abs +#include "functions/math.hpp" +#include "operators/binary_arithmetic.hpp" + #include "third_party/catch.hpp" @@ -19,6 +23,6 @@ TEST_CASE("Generate random BigInts having a specified number of digits", size_t num_digits; for (int i = 0; i < 50; i++) { num_digits = rand_generator() % 10000; - REQUIRE(big_random(num_digits).to_string().size() == num_digits); + REQUIRE(abs(big_random(num_digits)).to_string().size() == num_digits); } } From d99b98fc2bed75f82a3a0ce2e2b0111302a788ba Mon Sep 17 00:00:00 2001 From: B1Z0N Date: Thu, 22 Aug 2019 16:07:25 +0300 Subject: [PATCH 3/5] Added right description for big_int function, and some distributions Returned positive number generation, that was removed due to misconception --- include/functions/random.hpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/include/functions/random.hpp b/include/functions/random.hpp index 82cf8e3..cfda809 100644 --- a/include/functions/random.hpp +++ b/include/functions/random.hpp @@ -20,7 +20,7 @@ const size_t MAX_RANDOM_LENGTH = 1000; /* big_random (num_digits) ----------------------- - Returns a random BigInt with a specific number of digits. + Returns a random positive BigInt with a specific number of digits. */ BigInt big_random(size_t num_digits = 0) { @@ -36,25 +36,24 @@ BigInt big_random(size_t num_digits = 0) { static std::seed_seq sseq{std::random_device{}()}; // generator itself static std::mt19937 gen{sseq}; + // different purpose distributions(cheap to create and use) static std::uniform_int_distribution<> digit_distr(0, 9); - static std::uniform_int_distribution<> first_digit_distr(-9, 9); + static std::uniform_int_distribution<> first_digit_distr(0, 9); + static std::uniform_int_distribution<> length_distribution(1, MAX_RANDOM_LENGTH); // number to generate static BigInt big_rand; - if (num_digits == 0) { + // first digit + big_rand.value = std::to_string(first_digit_distr(gen)); + + if (num_digits == 0) // the number of digits were not specified // use a random number for it: - num_digits = 1 + gen() % MAX_RANDOM_LENGTH; - } - - // first digit and sign - auto first_digit = first_digit_distr(gen); - big_rand.value = std::to_string(abs(first_digit)); - big_rand.sign = first_digit < 0 ? '-' : '+'; + num_digits = length_distribution(gen); // insert other digits while (big_rand.value.size() < num_digits) - big_rand.value += std::to_string(digit_distr(gen)); + big_rand.value += std::to_string(digit_distr(gen)); return big_rand; } From b10f0d84681c38b1b8aee71ec79cbacaa7222e4d Mon Sep 17 00:00:00 2001 From: B1Z0N Date: Thu, 22 Aug 2019 16:07:57 +0300 Subject: [PATCH 4/5] Returned previouse state of tests, all passed --- test/functions/random.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/functions/random.cpp b/test/functions/random.cpp index e6d50ae..3d7b113 100644 --- a/test/functions/random.cpp +++ b/test/functions/random.cpp @@ -5,10 +5,6 @@ #include "functions/random.hpp" #include "operators/io_stream.hpp" -// for abs -#include "functions/math.hpp" -#include "operators/binary_arithmetic.hpp" - #include "third_party/catch.hpp" @@ -23,6 +19,6 @@ TEST_CASE("Generate random BigInts having a specified number of digits", size_t num_digits; for (int i = 0; i < 50; i++) { num_digits = rand_generator() % 10000; - REQUIRE(abs(big_random(num_digits)).to_string().size() == num_digits); + REQUIRE(big_random(num_digits).to_string().size() == num_digits); } } From 8dc5c8ed33c318685445e3aea1a397b75c847105 Mon Sep 17 00:00:00 2001 From: B1Z0N Date: Thu, 22 Aug 2019 16:12:32 +0300 Subject: [PATCH 5/5] Fixed big_random description --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 983df01..64c9df2 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ BigInt

Arbitrary-sized integer class for C++

- --- [![Release version][release-shield]][release-link] @@ -200,14 +199,14 @@ * #### Random * #### `big_random` - Get a random `BigInt`, that either has a random number of digits (up to + Get a random positive `BigInt`, that either has a random number of digits (up to 1000), or a specific number of digits. ```c++ - // get a random BigInt that has a random number of digits (up to 1000): + // get a random postive BigInt that has a random number of digits (up to 1000): big1 = big_random(); - // get a random BigInt that has 12345 digits: + // get a random positive BigInt that has 12345 digits: big1 = big_random(12345); ```