C++. Розробка класу Random для генерування випадкових чисел

Розробка класу Random для генерування випадкових чисел

Перед використанням даної теми рекомендується ознайомитись з темою:


Зміст


Пошук на інших ресурсах:




Умова задачі

Розробити клас Random, який містить засоби для генерування послідовностей випадкових чисел. Продемонструвати роботу класу. Програму розробити як Console Application.

 

Розв’язок

1. Оголосити внутрішні змінні min, max

На першому кроці вводяться внутрішні змінні. У нашому випадку в розділ private потрібно ввести змінні з наступними іменами:

  • min – нижня межа діапазону випадкових чисел;
  • max – верхня межа діапазону випадкових чисел.

Внутрішні змінні min, max мають тип double. Клас підтримує роботу з як цілими числами так із дійсними числами.

На даному етапі вихідний код програми наступний:

#include <iostream>
#include <stdlib.h> // потрібен для виклику функції rand(), srand()
#include <time.h> // потрібен для виклику функції time()
using namespace std;

// Клас Random
class Random
{
private:
  double min, max; // Діапазон генерування
}

 

2. Ініціалізація. Конструктори класу

В конструкторах розміщується код встановлення початкового значення (стартової точки) для подальшого генерування послідовностей

srand(time(NULL));

Отже, у конструкторі для кожного створеного екземпляру класу сворюється власна стартова точка. Кожен екземпляр класу буде генерувати власну унікальну послідовність випадкових чисел.

Текст конструкторів класу наступний

...

// Клас Random
class Random
{
private:
  double min, max; // Діапазон генерування

public:
  // Конструктори класу
  // Конструктор без параметрів, ініціалізувати генератор чисел.
  // За замовчуванням встановлюється діапазон [0, 100].
  Random(double min, double max)
  {
    srand(time(NULL));

    // Корегування, якщо неправильно задані межі
    if (max > min)
    {
      this->min = max;
      this->max = min;
    }
    else
    {
      this->min = min;
      this->max = max;
    }
  }

  // Конструктор з двома параметрами, що встановлюють діапазон
  // генерування випадкових чисел
  Random(double min, double max)
  {
    srand(time(NULL));
    this->min = min;
    this->max = max;
  }
}

 

3. Функції, що генерують одиночні випадкові числа

При генеруванні випадкових чисел базовими методами класу є методи генерування одиночних випадкових чисел. У класі реалізовано генерування як цілих чисел, так і чисел з плаваючою комою.

3.1. Функції NextInt(). Генерування цілих чисел

Для генерування цілих чисел використовуються дві функції, які різняться вхідними праметрами. Одна з функцій (з двома параметрами) в якості вхідних параметрів отримує мінімальне та максимальне значення, які формують діапазон отриманого числа. Інша функція (без параметрів) використовує значення внутрішніх змінних класу min, max для формування діапазону згенерованих чисел.

// Функція генерування випадкового цілого числа в заданих межах.
// Діапазон чисел: [min, max]
int NextInt(int min, int max)
{
  // Отримати випадкове число - формула
  int num = min + rand() % (max - min + 1);
  return num;
}

// Функція генерування випадкового цілого числа на основі
// даних поточного екземпляру.
int NextInt()
{
  return NextInt((int)this->min, (int)this->max);
}

  

3.2. Функції NextFloat(). Генерування чисел з плаваючою комою

Для роботи з числами з плаваючою комою в класі реалізовано дві перевантажені функції NextFloat(). Одна з функцій повертає число з плаваючою комою для діапазону значень (min, max), який задається як параметр функції. Друга функція повертає число з плаваючою комою для діапазону значень (min, max), який заданий у внутрішніх полях екземпляру класу.

Обидві функції побудовані таким чином, що дозволяють отримати число з плаваючою комою з заданою точністю. Точність задається цілим числом, яке рівне кількості знаків після коми.

Текст функцій наступний:

// Функція, яка генерує випадкове число з плаваючою комою і заданою точністю.
// Функція отримує 3 параметри:
// - min - нижня межа;
// - max - верхня межа;
// - precision - точність, кількість знаків після коми.
double NextFloat(double min, double max, int precision = 2)
{
  double value;

  // отримати випадкове число як ціле число з порядком precision
  value = rand() % (int)pow(10, precision);

  // отримати дійсне число
  value = min + (value / pow(10, precision )) * (max - min);

  return value;
}

// Перевантажений варіант NextFloat(), функція отримує параметр - точність.
// Діапазон визначається на основі заданого екземпляру.
double NextFloat(int precision = 2)
{
  double value;

  // отримати випадкове число як ціле число з порядком precision
  value = rand() % (int)pow(10, precision);

  // отримати дійсне число
  value = min + (value / pow(10, precision)) * (max - min);

  return value;
}

  

4. Функції GetArrayInt() та GetArrayFloat(). Формування послідовностей (масивів) чисел

Для розширення можливостей класу Random, в ньому введено дві додаткові функції:

  • функція GetArrayInt() повертає покажчик на масив цілих чисел, згенерованих випадково;
  • функція GetArrayFloat() повертає покажчик на масив випадкових чисел з плаваючою комою.

Функції виділяють пам’ять для результуючого масиву. Цю пам’ять потрібно звільнити після використання у викликаючому коді.

// Метод, що повертає масив цілих чисел в діапазоні,
// що встановлений значеннями min, max поточного екземпляру.
// Вхідний параметр count - кількість чисел в масиві
int* GetArrayInt(int count)
{
  int* A = new int[count];
  for (int i = 0; i < count; i++)
    A[i] = NextInt();
  return A;
}

// Метод, що повертає масив дійсних чисел в діапазоні,
// що встановлений в заданому екземплярі.
// Вхідні параметри:
// - count - кількість чисел в масиві;
// - precision - точність (кількість знаків після коми).
double* GetArrayFloat(int count, int precision = 2)
{
  double* A = new double[count];
  for (int i = 0; i < count; i++)
    A[i] = NextFloat(precision);
  return A;
}

  

5. Функції SetMinMax(), GetMin(), GetMax(). Доступ до внутрішніх змінних

Інколи виникає необхідність змінити або прочитати діапазон значень, які генеруються методами екземпляру класу Random. Для цього в класі реалізовано методи доступу до змінних min, max.

// ----------- Методи доступу до внутрішніх змінних ----------
void SetMinMax(double min, double max)
{
  this->min = min;
  this->max = max;
}

double GetMin()
{
  return min;
}

double GetMax()
{
  return max;
}

  

6. Функція main(). Демонстрація використання класу Random

У функції main() демонструється використання класу Random. Текст функції наступний:

void main()
{
  // 1. Оголосити екземпляри класу
  Random R1(0, 5); // викликається конструктор з 2 параметрами
  Random R2; // викликається конструктор без параметрів

  // 2. Перевірка методу NextInt()
  int d1 = R1.NextInt();
  int d2 = R1.NextInt();

  cout << "d1 = " << d1 << endl;
  cout << "d2 = " << d2 << endl;

  // 3. Демонстрація методу GetArrayInt()
  int* D = R1.GetArrayInt(20); // виділяється пам'ять для масиву D
  cout << "Array D: ";
  for (int i = 0; i < 20; i++)
    cout << D[i] << " ";
  cout << endl;

  delete[] D; // не забути звільнити пам'ять

  // 4. Ініціалізація іншим екземпляром класу
  Random R3 = R1;
  double* X = R3.GetArrayFloat(10, 4); // виділяється пам'ять

  cout << "Array X: ";
  for (int i = 0; i < 10; i++)
    cout << X[i] << " ";
  cout << endl;

  delete[] X; // звільнити пам'ять

  // 5. Встановити нові межі в екземплярі R1
  R1.SetMinMax(19, 13); // числа в діапазоні [13; 19]

  // Згенерувати нову послідовність в R1
  double* X2 = R1.GetArrayFloat(10, 3);

  cout << "Array X2:";
  for (int i = 0; i < 10; i++)
    cout << X2[i] << " ";
  cout << endl;

  delete[] X2;
}

  

7. Текст усієї програми (скорочений варіант)

У скороченому вигляді текст класу Random наступний:

#include <iostream>
#include <stdlib.h> // потрібен для виклику функції rand(), srand()
#include <time.h> // потрібен для виклику функції time()
using namespace std;

// Клас Random
class Random
{
private:
  double min, max; // Діапазон генерування

public:
  // ----------- Конструктори класу ----------------------
  // Конструктор без параметрів, ініціалізувати генератор чисел.
  // За замовчуванням встановлюється діапазон [0, 100].
  Random()
  {
    ...
  }

  // Конструктор з двома параметрами, які встановлюють діапазон
  // генерування випадкових чисел
  Random(double min, double max)
  {
    ...
  }

  // ------ Методи генерування одиночних випадкових чисел --------
  // Функція генерування випадкового цілого числа на основі
  // даних поточного екземпляру.
  int NextInt()
  {
    ...
  }

  // Функція генерування випадкового цілого числа в заданих межах.
  // Діапазон чисел: [min, max]
  int NextInt(int min, int max)
  {
    ...
  }

  // Функція, яка генерує випадкове число з плаваючою комою і заданою точністю.
  // Функція отримує 3 параметри:
  // - min - нижня межа;
  // - max - верхня межа;
  // - precision - точність, кількість знаків після коми.
  double NextFloat(double min, double max, int precision = 2)
  {
    ...
  }

  // Перевантажений варіант NextFloat(), функція отримує параметр - точність.
  // Діапазон визначається на основі заданого екземпляру.
  double NextFloat(int precision = 2)
  {
    ...
  }

  // ---------- Методи генерування послідовностей -------------------
  // Метод, що повертає масив цілих чисел в діапазоні,
  // що встановлений значеннями min, max поточного екземпляру.
  // Вхідний параметр count - кількість чисел в масиві
  int* GetArrayInt(int count)
  {
    ...
  }

  // Метод, що повертає масив дійсних чисел в діапазоні,
  // що встановлений в заданому екземплярі.
  // Вхідні параметри:
  // - count - кількість чисел в масиві;
  // - precision - точність (кількість знаків після коми).
  double* GetArrayFloat(int count, int precision = 2)
  {
    ...
  }

  // ----------- Методи доступу до внутрішніх змінних ----------------
  void SetMinMax(double min, double max)
  {
    ...
  }

  double GetMin()
  {
    ...
  }

  double GetMax()
  {
    ...
  }
};

void main()
{
  ...
}

  


Зв’язані теми