← Назад к вопросам

Как бы переделал реализацию рандомайзера для значений true и false, чтобы она генерировала случайные числа 1, 2, 3?

2.0 Middle🔥 101 комментариев
#PHP Core

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Рефакторинг рандомайзера boolean в генератор чисел

Если изначально имеется реализация, генерирующая случайные значения true/false, и её нужно адаптировать для генерации чисел 1, 2, 3, потребуется внести несколько ключевых изменений в логику работы. Рассмотрим поэтапный процесс рефакторинга.

1. Анализ исходной реализации

Предположим, исходный код выглядел примерно так:

class BooleanRandomizer {
    public function generate(): bool {
        return mt_rand(0, 1) === 1;
    }
    
    public function generateMultiple(int $count): array {
        $results = [];
        for ($i = 0; $i < $count; $i++) {
            $results[] = $this->generate();
        }
        return $results;
    }
}

Эта реализация использует равномерное распределение между двумя значениями через сравнение с 1.

2. Стратегии переработки

Для генерации чисел 1, 2, 3 нужно:

A. Прямая модизация метода generate()

Самый простой подход — изменить логику генерации:

class NumberRandomizer {
    public function generate(): int {
        return mt_rand(1, 3);
    }
}

B. Расширение функциональности через параметры

Более гибкое решение с конфигурируемым диапазоном:

class ConfigurableRandomizer {
    private int $min;
    private int $max;
    
    public function __construct(int $min = 1, int $max = 3) {
        $this->min = $min;
        $this->max = $max;
    }
    
    public function generate(): int {
        return mt_rand($this->min, $this->max);
    }
}

// Использование
$randomizer = new ConfigurableRandomizer(1, 3);
$value = $randomizer->generate(); // 1, 2 или 3

C. Реализация через стратегию

Паттерн "Стратегия" для поддержки разных распределений:

interface RandomizationStrategy {
    public function generate(): int;
}

class UniformDistributionStrategy implements RandomizationStrategy {
    private int $min;
    private int $max;
    
    public function __construct(int $min, int $max) {
        $this->min = $min;
        $this->max = $max;
    }
    
    public function generate(): int {
        return mt_rand($this->min, $this->max);
    }
}

class WeightedDistributionStrategy implements RandomizationStrategy {
    private array $weights;
    
    public function __construct(array $weights) {
        $this->weights = $weights;
    }
    
    public function generate(): int {
        $total = array_sum($this->weights);
        $random = mt_rand(1, $total);
        
        foreach ($this->weights as $number => $weight) {
            $random -= $weight;
            if ($random <= 0) {
                return $number;
            }
        }
        
        return array_key_first($this->weights);
    }
}

// Использование с равномерным распределением
$uniform = new UniformDistributionStrategy(1, 3);
$value = $uniform->generate();

// Использование с взвешенным распределением (например, 1:20%, 2:30%, 3:50%)
$weighted = new WeightedDistributionStrategy([1 => 20, 2 => 30, 3 => 50]);
$value = $weighted->generate();

3. Криптографически безопасная альтернатива

Для приложений, требующих криптографической безопасности:

class SecureRandomizer {
    private int $min;
    private int $max;
    
    public function __construct(int $min = 1, int $max = 3) {
        $this->min = $min;
        $this->max = $max;
    }
    
    public function generate(): int {
        $range = $this->max - $this->min;
        $bits = ceil(log($range + 1, 2));
        $bytes = ceil($bits / 8);
        
        do {
            $random = hexdec(bin2hex(random_bytes($bytes)));
            $value = $random % ($range + 1);
        } while ($random - $value > (PHP_INT_MAX - $range));
        
        return $value + $this->min;
    }
}

4. Тестирование и валидация

После рефакторинга важно протестировать распределение:

class RandomizerTest {
    public function testDistribution(RandomizationStrategy $randomizer, int $iterations = 10000): array {
        $results = [];
        
        for ($i = 0; $i < $iterations; $i++) {
            $value = $randomizer->generate();
            $results[$value] = ($results[$value] ?? 0) + 1;
        }
        
        foreach ($results as $value => $count) {
            $results[$value] = $count / $iterations * 100;
        }
        
        return $results;
    }
}

// Проверка равномерности распределения
$randomizer = new UniformDistributionStrategy(1, 3);
$distribution = (new RandomizerTest())->testDistribution($randomizer);
// Ожидаем ~33.3% для каждого значения

5. Рекомендации по реализации

  1. Выбор ГСЧ:

    • mt_rand() достаточно для большинства задач
    • random_int() для криптографической безопасности
  2. Инкапсуляция логики: Лучше вынести генерацию в отдельный класс с интерфейсом

  3. Расширяемость: Предусмотреть возможность изменения диапазона и распределения

  4. Производительность: Для bulk-генерации можно оптимизировать:

class BulkRandomizer {
    public function generateBatch(int $count, int $min = 1, int $max = 3): array {
        $results = [];
        for ($i = 0; $i < $count; $i++) {
            $results[] = mt_rand($min, $max);
        }
        return $results;
    }
}

Таким образом, переход от генерации boolean к числам 1-3 требует изменения типа возвращаемого значения и логики выбора случайного элемента из множества трёх значений вместо двух. Наиболее правильным подходом будет создание гибкой, тестируемой системы с чёткими интерфейсами и поддержкой различных сценариев использования.