{"id":13731442,"url":"https://github.com/ilqvya/random","last_synced_at":"2026-01-11T23:52:04.567Z","repository":{"id":39352116,"uuid":"91072215","full_name":"ilqvya/random","owner":"ilqvya","description":"Random for modern C++ with convenient API","archived":false,"fork":false,"pushed_at":"2025-03-22T03:10:57.000Z","size":382,"stargazers_count":916,"open_issues_count":0,"forks_count":84,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-04-06T17:07:29.511Z","etag":null,"topics":["cpp11","header-only","random"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ilqvya.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":"FUNDING.yml","license":"LICENSE.MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["ilqvya"]}},"created_at":"2017-05-12T09:01:02.000Z","updated_at":"2025-03-22T03:11:01.000Z","dependencies_parsed_at":"2024-04-04T21:45:01.593Z","dependency_job_id":"fc09baf3-2234-46a2-8c83-449616876ca2","html_url":"https://github.com/ilqvya/random","commit_stats":null,"previous_names":["ilqvya/random","effolkronium/random"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilqvya%2Frandom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilqvya%2Frandom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilqvya%2Frandom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ilqvya%2Frandom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ilqvya","download_url":"https://codeload.github.com/ilqvya/random/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248781335,"owners_count":21160706,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp11","header-only","random"],"created_at":"2024-08-03T02:01:30.243Z","updated_at":"2026-01-11T23:52:04.552Z","avatar_url":"https://github.com/ilqvya.png","language":"C++","readme":"# Random for modern C++ with convenient API\n[![Github-sponsors](https://img.shields.io/badge/sponsor-30363D?style=for-the-badge\u0026logo=GitHub-Sponsors\u0026logoColor=#EA4AAA)](https://github.com/sponsors/ilqvya)\n[![Build status](https://ci.appveyor.com/api/projects/status/nukrsqimulgel7nk?svg=true)](https://ci.appveyor.com/project/ilqvya/random)\n[![Coverage Status](https://coveralls.io/repos/github/effolkronium/random/badge.svg?branch=master\u0026unused=0)](https://coveralls.io/github/effolkronium/random?branch=master\u0026unused=0)\n\u003ca href=\"https://scan.coverity.com/projects/ilqvya-random\"\u003e\u003cimg alt=\"Coverity Scan Build Status\" src=\"https://scan.coverity.com/projects/31956/badge.svg\"/\u003e\u003c/a\u003e\n[![Github-sponsors](https://img.shields.io/badge/sponsor-30363D?style=for-the-badge\u0026logo=GitHub-Sponsors\u0026logoColor=#EA4AAA)](https://github.com/sponsors/ilqvya)\n- [Design goals](#design-goals)\n- [Supported compilers](#supported-compilers)\n- [Integration](#integration)\n- [Five-minute tutorial](#five-minute-tutorial)\n  - [Number range](#number-range)\n  - [Common type number range](#common-type-number-range)\n  - [Character range](#character-range)\n  - [Bool](#bool)\n  - [Random value from std::initializer_list](#random-value-from-stdinitializer_list)\n  - [Random iterator](#random-iterator)\n  - [Random element from array](#random-element-from-array)\n  - [Container of random values](#container-of-random-values)\n  - [Weighted random values](#weighted-random-values)\n  - [Shuffle](#shuffle)\n  - [Custom distribution](#custom-distribution)\n  - [Custom Seeder](#custom-seeder)\n  - [Thread local random](#thread-local-random)\n  - [Local random](#local-random)\n  - [engine](#engine)\n  - [Get engine](#get-engine)\n  - [Seeding](#seeding)\n  - [min-value](#min-value)\n  - [max-value](#max-value)\n  - ['get' without arguments](#get-without-arguments)\n  - [Discard](#discard)\n  - [Is equal](#is-equal)\n  - [Serialize](#serialize)\n  - [Deserialize](#deserialize)\n## Design goals\nThere are few ways to get working with random in C++:\n- **C style**\n```cpp\n  srand( time(NULL) ); // seed with time since epoch\n  auto random_number = (rand() % 9) + 1; // get a pseudo-random integer between 1 and 9\n```\n* Problems\n  * should specify seed\n  * should write your own distribution algorithm\n  * [There are no guarantees as to the quality of the random sequence produced.](http://en.cppreference.com/w/cpp/numeric/random/rand#Notes)\n- **C++11 style**\n```cpp\n  std::random_device random_device; // create object for seeding\n  std::mt19937 engine{random_device()}; // create engine and seed it\n  std::uniform_int_distribution\u003c\u003e dist(1,9); // create distribution for integers with [1; 9] range\n  auto random_number = dist(engine); // finally get a pseudo-random integer number\n```\n* Problems\n  * should specify seed\n  * should choose, create and use a chain of various objects like engines and distributions\n  * [mt19937](http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine) uses 5000 bytes of memory for each creation (which is bad for performance if we create it too frequently)\n  * uncomfortable and not intuitively clear usage\n- **effolkronium random style**\n```cpp\n  // auto seeded\n  auto random_number = Random::get(1, 9); // invoke 'get' method to generate a pseudo-random integer in [1; 9] range\n  // yep, that's all.\n```\n* Advantages\n  * **Intuitive syntax**. You can do almost everything with random by simple 'get' method, like getting simple numbers, bools, random object from given set or using custom distribution.\n  * **Trivial integration**. All code consists of a single header file [`random.hpp`](https://github.com/effolkronium/random/blob/master/include/effolkronium/random.hpp). That's it. No library, no subproject, no dependencies, no complex build system. The class is written in vanilla C++11. All in all, everything should require no adjustment of your compiler flags or project settings.\n  * **Usability**. There are 3 versions of random: \n    * *random_static* which has static methods and static internal state. It's not thread safe but more efficient\n    * *random_thread_local* which has static methods and [thread_local](http://en.cppreference.com/w/cpp/keyword/thread_local) internal state. It's thread safe but less efficient\n    * *random_local* which has non static methods and local internal state. It can be created on the stack at local scope\n## Supported compilers\n* GCC 4.9 - 13.1.0 (and possibly later)\n* Clang 3.7 - 15.0.0 (and possibly later)\n* Microsoft Visual C++ 2015 - 2022 (and possibly later)\n## Integration\n#### CMake\n* As subproject\n```cmake\nadd_subdirectory(random) # path to the 'random' library root\n... # create target\ntarget_link_libraries(${TARGET} effolkronium_random) # add include path to a compiler\n```\n* As external project\n\nFirst of all, build or|and install this project:\n```cmd\ncd \"path_to_root_of_the_library\"\nmkdir build\ncd build\ncmake -G\"Visual Studio 15 2017\" ..\ncmake --build . --target install --config Release\nctest -C Release\n```\nThen, find the package by a cmake\n```cmake\nfind_package(effolkronium_random REQUIRED)\n... # create target\ntarget_link_libraries(${TARGET} effolkronium_random)\n```\n#### Manually\nThe single required source, file [`random.hpp`](https://github.com/effolkronium/random/blob/master/include/effolkronium/random.hpp) is in the [`include/effolkronium`](https://github.com/effolkronium/random/tree/master/include/effolkronium) directory.\n#### Then\nAll you need to do is add\n```cpp\n#include \"effolkronium/random.hpp\"\n\n// get base random alias which is auto seeded and has static API and internal state\nusing Random = effolkronium::random_static;\n```\nto the files you want to use effolkronium random class. That's it. Do not forget to set the necessary switches to enable C++11 (e.g., `-std=c++11` for GCC and Clang).\n## Five-minute tutorial\n### Number range\nReturns a pseudo-random number in a [first; second] range.\n```cpp\nauto val = Random::get(-1, 1) // decltype(val) is int\n```\n```cpp\n// specify explicit type\nauto val = Random::get\u003cuint8_t\u003e(-1, 1) // decltype(val) is uint8_t\n```\n```cpp\n// you able to use range from greater to lower\nauto val = Random::get(1.l, -1.l) // decltype(val) is long double\n```\n```cpp\nauto val = Random::get(1.f, -1) // Error: implicit conversions are not allowed here.\n```\n### Common type number range\nChoose common type of two range arguments by std::common_type.\n```cpp\nauto val = Random::get\u003cRandom::common\u003e(1, 0.f) // decltype(val) is float\n```\n```cpp\nauto val = Random::get\u003cRandom::common\u003e(0ul, 1ull) // decltype(val) is unsigned long long\n```\n```cpp\nauto val = Random::get\u003cRandom::common\u003e(1.2l, 1.5f) // decltype(val) is long double\n```\n```cpp\nauto val = Random::get\u003cRandom::common\u003e(1u, -1) // Error: prevent conversion from signed to unsigned.\n```\n### Character range\nReturns a pseudo-random character in a [first; second] range.\n```cpp\nauto val = Random::get('a', 'z')\n```\n```cpp\nauto val = Random::get(L'㋐', L'㋾')\n```\n```cpp\nauto val = Random::get\u003cwchar_t\u003e()\n```\n### Bool\nGenerate true with [0; 1] probability\n```cpp\nauto val = Random::get\u003cbool\u003e(0.7) // true with 70% probability\n```\n```cpp\nauto val = Random::get\u003cbool\u003e() // true with 50% probability by default\n```\n```cpp\nauto val = Random::get\u003cbool\u003e(-1) // Error: assert occurred! Out of [0; 1] range\n```\n### Random value from std::initializer_list\nReturn random value from values in a std::initializer_list\n```cpp\nauto val = Random::get({1, 2, 3}) // val = 1 or 2 or 3\n```\n### Random iterator\nReturn random iterator from iterator range or container.\nIterator must be at least [Input iterator](http://en.cppreference.com/w/cpp/named_req/InputIterator).\nIf a std::distance(first, last) == 0, return the 'last' iterator.\nIf container is empty, return [std::end](http://en.cppreference.com/w/cpp/iterator/end)(container) iterator.\n```cpp\nstd::array\u003cint, 3\u003e array{ {1, 2, 3} };\n```\n* Iterator range\n```cpp\nauto randomIt = Random::get( array.begin(), array.end() );\n```\n* Container\n```cpp\nauto randomIt = Random::get( array );\n```\n### Random element from array\nReturn pointer to random element in built-in array\n```cpp\nint array [] = {1, 2, 3};\nauto randomPtr = Random::get( array );\n```\n### Container of random values\nReturn container filled with random numbers.\nAny containers with \"begin\", \"end\" and \"insert\" methods are applicable\n```cpp\nauto vec = Random::get\u003cstd::vector\u003e(1, 9, 5); // decltype(vec) is std::vector\u003cint\u003e with size = 5\n// Note: \"reserve\" method invokes automatically for performance\n\nauto mset = Random::get\u003cstd::multiset\u003e(1.0, 9.9, 10); // decltype(mset) is std::multiset\u003cdouble\u003e with size = 10\n\nauto arr = Random::get\u003cstd::array, 5\u003e('0', '9'); // decltype(arr) is std::array\u003cchar, 5\u003e\n// Warning: Returning arrays with large size could be ineficcient\n\nauto vec = Random::get\u003cstd::vector\u003e(1l, 9ll, 5); // decltype(vec) is std::vector\u003clong long\u003e with size = 5\n\ntemplate\u003ctypename T\u003e\nclass MyContainer\n{\n    iterator begin() {...}\n    iterator end() {...}\n    void insert(iterator after, T value) {...}\n};\n\nauto vec = Random::get\u003cMyContainer\u003e(1, 9, 5); // decltype(vec) is std::MyContainer\u003cint\u003e with size = 5\n\n```\n### Weighted random values\nReturn random iterator from map-like containers\n```cpp\n    std::unordered_map\u003cstd::string, unsigned long\u003e nonzero_ulong_umap = {{\"Orange\", 1ul}, {\"Apple\", 2ul}, {\"Banana\", 3ul}};\n    std::unordered_map\u003cstd::string, unsigned\u003e nonzero_uint_umap = {{\"Orange\", 1u}, {\"Apple\", 2u}, {\"Banana\", 3u}};\n    \n    std::map\u003cstd::string, float\u003e nonzero_float_map = {{\"Orange\", 1.0f}, {\"Apple\", 2.0f}, {\"Banana\", 3.0f}};\n    std::map\u003cstd::string, double\u003e nonzero_double_map = {{\"Orange\", 1.0}, {\"Apple\", 2.0}, {\"Banana\", 3.0}};\n\n    Random::get\u003cRandom_t::weight\u003e(nonzero_ulong_umap);\n    Random::get\u003cRandom_t::weight\u003e(nonzero_uint_umap);\n    Random::get\u003cRandom_t::weight\u003e(nonzero_float_map);\n    Random::get\u003cRandom_t::weight\u003e(nonzero_double_map);\n```\n### Shuffle\nReorders the elements in a given range or in all container [ref](http://en.cppreference.com/w/cpp/algorithm/random_shuffle)\n```cpp\nstd::array\u003cint, 3\u003e array{ {1, 2, 3} };\n```\n* Iterator range\n```cpp\nRandom::shuffle( array.begin( ), array.end( ) )\n```\n* Container\n```cpp\nRandom::shuffle( array )\n```\n### Custom distribution\nReturn result from operator() of a distribution with internal random engine argument\n* Template argument\n```cpp\n// 1.f and 2.f will be forwarded to std::gamma_distribution constructor\nauto result = Random::get\u003cstd::gamma_distribution\u003c\u003e\u003e( 1.f, 2.f );\n```\n* Argument by reference\n```cpp\nstd::gamma_distribution\u003c\u003e gamma{ 1.f, 2.f };\nauto result = Random::get( gamma ); // return result of gamma.operator()( engine_ )\n```\n### Custom Seeder\nSpecify seed by which random engine will be seeded at construction time:\n* Number\n```cpp\nstruct MySeeder {\n    unsigned operator() () {\n        return 42u;\n    }\n};\n    \n// Seeded by 42\nusing Random = effolkronium::basic_random_static\u003cstd::mt19937, MySeeder\u003e;\n```\n* Seed sequence\n\nBecause we can't copy std::seed_seq, the 'random' library destroy seeder instance after engine seeding. So it's safe to return seed by reference.\n```cpp\nstruct MySeeder {\n    // std::seed_seq isn't copyable\n    std::seed_seq\u0026 operator() () {\n        return seed_seq_;\n    }\n    std::seed_seq seed_seq_{ { 1, 2, 3, 4, 5 } };\n};\n    \n// Seeded by seed_seq_ from MySeeder\nusing Random = effolkronium::basic_random_static\u003cstd::mt19937, MySeeder\u003e;\n```\n* Reseed\n\nSeed an internal random engine by a newly created Seeder instance\n```cpp\nRandom::reseed( );\n```\n### Thread local random\nIt uses static methods API and data with [thread_local](http://en.cppreference.com/w/cpp/keyword/thread_local) storage which is fully **thread safe** (but less performance)\n```cpp\nusing Random = effolkronium::random_thread_local\n\n// use in the same way as random_static. Thread safe\nstd::thread first{ [ ] { Random::get( ); } };\nstd::thread second{ [ ] { Random::get( ); } };\n```\n### Local random\nIt uses non static methods API and data with auto storage which can be created on the stack at local scope\n```cpp\n#include \"effolkronium/random.hpp\"\n\nusing Random_t = effolkronium::random_local\n\nint main( ) {\n  Random_t localRandom{ }; // Construct on the stack\n  \n  // access throughout dot\n  auto val = localRandom.get(-10, 10);\n  \n} // Destroy localRandom and free stack memory\n```\n### Seeding\n[ref](http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine/seed)\n\nSet new seed for an internal random engine.\n```cpp\nRandom::seed( 10 ); // 10 is new seed number\n\nstd::seed_seq sseq{ 1, 2, 3 };\nRandom::seed( sseq ); // use seed sequence here\n```\n### Min value\n[ref](http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine/min)\n\nReturns the minimum value potentially generated by the internal random-number engine\n```cpp\nauto minVal = Random::min( );\n```\n### Max value\n[ref](http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine/max)\n\nReturns the maximum value potentially generated by the internal random-number engine\n```cpp\nauto maxVal = Random::max( );\n```\n### get without arguments\n[ref](http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine/operator())\n\nReturns the random number in [ Random::min( ), Random::max ] range\n```cpp\nauto val = Random::get( );\n// val is random number in [ Random::min( ), Random::max ] range\n```\n### engine\nReturns reference to the internal engine.\n```cpp\nauto\u0026 engine = Random::engine( );\n```\n```cpp\nstd::sample(itBeg, itEnd, std::back_inserter(out), 5, Random::engine( ));\n```\n### Get engine\nReturns copy of internal engine.\n```cpp\nauto engine = Random::get_engine( );\n```\n### Discard\n[ref](http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine/discard)\n\nAdvances the internal engine's state by a specified amount.\nEquivalent to calling Random::get() N times and discarding the result.\n```cpp\nRandom::discard( 500 );\n```\n### IsEqual\n[ref](http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine/operator_cmp)\n\nCompares internal pseudo-random number engine with other pseudo-random number engine.\n```cpp\nRandom::Engine otherEngine;\nbool isSame = Random::is_equal( otherEngine );\n```\n### Serialize\n[ref](http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine/operator_ltltgtgt)\n\nSerializes the internal state of the internal pseudo-random number engine as a sequence of decimal numbers separated by one or more spaces, and inserts it to the output stream. The fill character and the formatting flags of the stream are ignored and unaffected.\n```cpp\nstd::stringstream strStream;\nRandom::serialize( strStream ); // the strStream now contain internal state of the Random internal engine\n```\n### Deserialize\n[ref](http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine/operator_ltltgtgt)\n\nRestores the internal state of the internal pseudo-random number engine from the serialized representation, which was created by an earlier call to 'serialize' using a stream with the same imbued locale and the same CharT and Traits. If the input cannot be deserialized, internal engine is left unchanged and failbit is raised on input stream.\n```cpp\nstd::stringstream strStream;\nRandom::serialize( strStream );\n\n// ...\n\nRandom::deserialize( strStream ); // Restore internal state of internal Random engine\n```\n","funding_links":["https://github.com/sponsors/ilqvya"],"categories":["Maths"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filqvya%2Frandom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Filqvya%2Frandom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Filqvya%2Frandom/lists"}