Смотрите видео ниже, чтобы узнать, как установить наш сайт в качестве веб-приложения на домашнем экране.
Примечание: Эта возможность может быть недоступна в некоторых браузерах.
Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно. Вам необходимо обновить браузер или попробовать использовать другой.
В общем, у меня есть список допустим в нем 3 строки:
1
2
3
4
Я беру из списка случайную сроку, допустим он взял 3 и все его как будто зацикливает на этой цифре, в 80% случаев он будет выдавать 3.
Никто такого не замечал?
Бывало даже такое, 2 миллиона строк в файле, а он как будто упрется в районе 50 строк и берет только их в рабочий поток.
Поставил перемешивать список перед взятием, вроде стало лучше, но интересно у кого как?
На самом деле неважно как, ситуация будет такая-же. Слишком короткие выборки, подобные ситуации будут в любом случае. Если необходимо исключить такое, то нужно просто учитывать что после генерации числа Х запрещена его генарация на протяжении нескольких следующих итераций.
Работа криптографически стойкого генератора случайных чисел
Генерация 1000000
от 1 до 6
C#:
void DemonstrateSecureRandomness()
{
int totalIterations = 1000000;
int minValue = 1;
int maxValue = 6;
int[] counts = new int[maxValue - minValue + 1];
project.SendInfoToLog($"Генерируем {totalIterations} случайных чисел от {minValue} до {maxValue}");
for (int i = 0; i < totalIterations; i++)
{
int randomNumber = GenerateSecureRandomNumber(minValue, maxValue);
counts[randomNumber - minValue]++;
if (i < 20 || i > totalIterations - 20)
{
project.SendInfoToLog($"Итерация {i + 1}: Сгенерировано число {randomNumber}");
}
else if (i == 20)
{
project.SendInfoToLog("...");
}
}
project.SendInfoToLog("\nРезультаты:");
for (int i = 0; i < counts.Length; i++)
{
double percentage = (double)counts[i] / totalIterations * 100;
project.SendInfoToLog($"Число {i + minValue}: {counts[i]} раз ({percentage:F2}%)");
}
double expectedPercentage = 100.0 / (maxValue - minValue + 1);
double maxDeviation = 0;
for (int i = 0; i < counts.Length; i++)
{
double deviation = System.Math.Abs((double)counts[i] / totalIterations * 100 - expectedPercentage);
if (deviation > maxDeviation)
{
maxDeviation = deviation;
}
}
project.SendInfoToLog($"\nМаксимальное отклонение от ожидаемого значения: {maxDeviation:F2}%");
if (maxDeviation < 1)
{
project.SendInfoToLog("Распределение очень близко к равномерному", true);
}
else if (maxDeviation < 2)
{
project.SendInfoToLog("Распределение близко к равномерному", true);
}
else
{
project.SendInfoToLog("Распределение может быть неравномерным", false);
}
double chiSquare = 0;
for (int i = 0; i < counts.Length; i++)
{
double expected = expectedPercentage * totalIterations / 100;
chiSquare += System.Math.Pow(counts[i] - expected, 2) / expected;
}
project.SendInfoToLog($"\nЗначение хи-квадрат: {chiSquare:F4}");
project.SendInfoToLog("Для 3 степеней свободы и уровня значимости 0.05, критическое значение хи-квадрат равно 7.815");
if (chiSquare < 7.815)
{
project.SendInfoToLog("Распределение статистически равномерно", true);
}
else
{
project.SendInfoToLog("Распределение статистически неравномерно", false);
}
}
int GenerateSecureRandomNumber(int minValue, int maxValue)
{
if (minValue > maxValue)
throw new System.ArgumentOutOfRangeException("minValue");
if (minValue == maxValue)
return minValue;
var rng = System.Security.Cryptography.RandomNumberGenerator.Create();
long range = (long)maxValue - minValue + 1;
byte[] uint32Buffer = new byte[4];
while (true)
{
rng.GetBytes(uint32Buffer);
uint randomUInt = System.BitConverter.ToUInt32(uint32Buffer, 0);
long result = (long)(randomUInt % range);
if (randomUInt - result + (range - 1) >= randomUInt)
{
return (int)(minValue + result);
}
}
}
// Вызов функции демонстрации
DemonstrateSecureRandomness();
Результат:
Число 1: 166676 раз (16,67%)
Число 2: 166640 раз (16,66%)
Число 3: 166721 раз (16,67%)
Число 4: 166828 раз (16,68%)
Число 5: 166382 раз (16,64%)
Число 6: 166753 раз (16,68%)
Максимальное отклонение от ожидаемого значения: 0,03%
Значение хи-квадрат: 0,7096
Для 3 степеней свободы и уровня значимости 0.05, критическое значение хи-квадрат равно 7.815
Распределение статистически равномерно
Работа криптографически стойкого генератора случайных чисел
Генерация 1000000
от 1 до 6
C#:
void DemonstrateSecureRandomness()
{
int totalIterations = 1000000;
int minValue = 1;
int maxValue = 6;
int[] counts = new int[maxValue - minValue + 1];
project.SendInfoToLog($"Генерируем {totalIterations} случайных чисел от {minValue} до {maxValue}");
for (int i = 0; i < totalIterations; i++)
{
int randomNumber = GenerateSecureRandomNumber(minValue, maxValue);
counts[randomNumber - minValue]++;
if (i < 20 || i > totalIterations - 20)
{
project.SendInfoToLog($"Итерация {i + 1}: Сгенерировано число {randomNumber}");
}
else if (i == 20)
{
project.SendInfoToLog("...");
}
}
project.SendInfoToLog("\nРезультаты:");
for (int i = 0; i < counts.Length; i++)
{
double percentage = (double)counts[i] / totalIterations * 100;
project.SendInfoToLog($"Число {i + minValue}: {counts[i]} раз ({percentage:F2}%)");
}
double expectedPercentage = 100.0 / (maxValue - minValue + 1);
double maxDeviation = 0;
for (int i = 0; i < counts.Length; i++)
{
double deviation = System.Math.Abs((double)counts[i] / totalIterations * 100 - expectedPercentage);
if (deviation > maxDeviation)
{
maxDeviation = deviation;
}
}
project.SendInfoToLog($"\nМаксимальное отклонение от ожидаемого значения: {maxDeviation:F2}%");
if (maxDeviation < 1)
{
project.SendInfoToLog("Распределение очень близко к равномерному", true);
}
else if (maxDeviation < 2)
{
project.SendInfoToLog("Распределение близко к равномерному", true);
}
else
{
project.SendInfoToLog("Распределение может быть неравномерным", false);
}
double chiSquare = 0;
for (int i = 0; i < counts.Length; i++)
{
double expected = expectedPercentage * totalIterations / 100;
chiSquare += System.Math.Pow(counts[i] - expected, 2) / expected;
}
project.SendInfoToLog($"\nЗначение хи-квадрат: {chiSquare:F4}");
project.SendInfoToLog("Для 3 степеней свободы и уровня значимости 0.05, критическое значение хи-квадрат равно 7.815");
if (chiSquare < 7.815)
{
project.SendInfoToLog("Распределение статистически равномерно", true);
}
else
{
project.SendInfoToLog("Распределение статистически неравномерно", false);
}
}
int GenerateSecureRandomNumber(int minValue, int maxValue)
{
if (minValue > maxValue)
throw new System.ArgumentOutOfRangeException("minValue");
if (minValue == maxValue)
return minValue;
var rng = System.Security.Cryptography.RandomNumberGenerator.Create();
long range = (long)maxValue - minValue + 1;
byte[] uint32Buffer = new byte[4];
while (true)
{
rng.GetBytes(uint32Buffer);
uint randomUInt = System.BitConverter.ToUInt32(uint32Buffer, 0);
long result = (long)(randomUInt % range);
if (randomUInt - result + (range - 1) >= randomUInt)
{
return (int)(minValue + result);
}
}
}
// Вызов функции демонстрации
DemonstrateSecureRandomness();
Результат:
Число 1: 166676 раз (16,67%)
Число 2: 166640 раз (16,66%)
Число 3: 166721 раз (16,67%)
Число 4: 166828 раз (16,68%)
Число 5: 166382 раз (16,64%)
Число 6: 166753 раз (16,68%)
Максимальное отклонение от ожидаемого значения: 0,03%
Значение хи-квадрат: 0,7096
Для 3 степеней свободы и уровня значимости 0.05, критическое значение хи-квадрат равно 7.815
Распределение статистически равномерно
Решение конечно крутое, но зачем так сложно?
Берешь первое значение, работаешь с ним, кладешь в конец списка и все, эффект тот же самый реализация в разы проще