.. _random-numbers-vector-of-random-numbers: Vector of random numbers ------------------------ The first step is to generate a large number of random values and store them in a vector. By “large number,” of course, I mean 20. It’s always a good idea to start with a manageable number, to help with debugging, and then increase it later. The following function takes a single argument, the size of the vector. It allocates a new vector of ``int``\ s, and fills it with random values between 0 and ``upper_bound``. :: std::vector make_vector (std::size_t size, int upper_bound) { std::vector data (size); std::random_device r; std::default_random_engine eng(r()); for (int& value: data) { value = std::uniform_int_distribution {0, upper_bound} (eng); } return data; } The return type is ``std::vector``, which means that this function returns a vector of integers. To test this function, it is convenient to have a function that outputs the contents of a vector. :: void print (const std::vector& data) { for (const int& value: data) { cout << value << ' '; } } Notice that it is legal to pass ``vector``\ s by reference. In fact it is quite common, since it makes it unnecessary to copy the vector. Since ``print`` does not modify the vector, we declare the parameter ``const``. We use the same technique to get values out of the vector without copying every single one. Avoiding these kinds of copy operations makes code run faster. It is also less error prone. The following code generates a vector and outputs it: :: std::size_t num_values = 20; int upper_bound = 9; std::vector numbers = make_vector (num_values, upper_bound); print (numbers); On my machine the output is :: 1 9 9 5 9 5 5 2 8 6 2 7 1 0 5 6 2 7 5 6 which is pretty random-looking. Your results might be different. Try running the active code below! .. tb-code:: cpp :name: vector_of_rand_nums_AC_1 :caption: Example vector_of_rand_nums_AC_1 :compileargs: ['-Werror'] #include #include #include #include // forward declarations std::vector make_vector (std::size_t, int); void print (const std::vector&); int main() { std::size_t num_values = 20; int upper_bound = 9; std::vector numbers = make_vector (num_values, upper_bound); print (numbers); } std::vector make_vector (std::size_t size, int upper_bound) { std::vector data (size); std::random_device r; std::default_random_engine eng(r()); for (int& value: data) { value = std::uniform_int_distribution {0, upper_bound} (eng); } return data; } void print (const std::vector& data) { for (const int& value: data) { std::cout << value << ' '; } } If these numbers are really random, we expect each digit to appear the same number of times—twice each. In fact, the number 5 appears five times, and the numbers 3 and 4 never appear at all. Do these results mean the values are not really uniform? It’s hard to tell. With so few values, the chances are slim that we would get exactly what we expect. But as the number of values increases, the outcome should be more predictable. To test this theory, we’ll write some programs that count the number of times each value appears, and then see what happens when we increase ``num_values``. .. tb-group:: :name: self_check .. tb-tab:: Q1 .. tb-blank:: :name: vector_of_rand_nums_1 How should we declare the parameter, **vector**, if we don't intend to make any changes to it? {{blank}} .. tb-answer:: :regex: :match: const :feedback: Correct! :incorrect: Incorrect, Try again! .. tb-tab:: Q2 .. tb-choice:: :name: vector_of_rand_nums_2 As we store more and more random numbers in a vector, we expect its contents to be __________. - [x] more uniform Correct! - [ ] less uniform Incorrect! As we store more random numbers in a vector, we see that the frequencies of each number are approximately equal. - [ ] more normal Incorrect! The distribution of random numbers is not related to the normal distribution. - [ ] less normal Incorrect! The distribution of random numbers is not related to the normal distribution. .. tb-tab:: Q3 .. tb-choice:: :name: vector_of_rand_nums_3 Would compiling the following code lead to a compiler error? .. code-block:: cpp :linenos: void dostuff (const vector & vec) { for (size_t i = 0; i < vec.size(); i++) { vec[i] = vec[i] ; } } - [x] yes we would get a compile error Correct! we can't make changes to a vector we take in by constant reference - [ ] no we would not because values remain same. Even if we keep the values same we are editing a constant which is not allowed.