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()
{
  ...
}

   ⇑


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

  ⇑