Есть вот такая задача: Сгенерировать массив чисел, сумма которых составит 1. Кол-во чисел вводится с клавиатуры. Решение может быть любое главное получить итоговую сумму 1 (Не желательно большое кол-во нулей)
Генерируем N любых неотрицательных чисел.
Вычисляем их сумму.
Делим каждое на эту сумму.
Пример реализации:
int count = 10;
Random random = new Random();
int[] integers = new int[count];
long sum = 0;
for (int i = 0; i < count; ++i)
{
integers[i] = random.Next();
sum += integers[i];
}
double[] doubles = new double[count];
for (int i = 0; i < count; ++i)
doubles[i] = (double)integers[i] / sum;
Console.WriteLine(string.Join("\n", doubles));
Console.WriteLine(doubles.Sum());
random.Next()
возвращает неотрицательное случайное целое число.
Для накопления суммы берем long
-переменную во избежание переполнений.
rnd
- Random
static double[] Generate(int count)
{
var result = new double[count];
var max = 1.0;
for (int i = 0; i < count - 1; i++)
{
result[i] = rnd.NextDouble() * max;
max -= result[i];
}
result[count-1] = max;
return result;
}
Дополнительно массив можно перемешать если критично то, что при такой генерации в среднем следующее значение становится меньше предыдущего. Пример простого перемешивания:
result.OrderBy(x => rnd.Next()).ToArray();
Ну, раз ограничений никаких нет, то самое примитивное решение: массив в котором первый элемент равен 1, а остальные — 0.
int n = 5;
var arr = new decimal[n];
arr[0] = 1;
ОБНОВЛЕНИЕ: Добавлено уточнение, что много нулей нежелательно. Из-за этого решение не подходит.
Вариант №2: Заполняем массив значениями 1/n:
int n = 6;
var value = 1.0m/n;
var arr = Enumerable.Repeat(value, n).ToArray();
Тут возникает проблема: из-за ошибок округления при делении, сумма может не сойтись. Для того, чтобы сумма сошлась компенсируем первый элемент:
arr[0] = 1-(value*(n-1));
Выбранный (на данный момент) вариант с делением на сумму заранее сгенерированных чисел не дает равномерного распределения результата из-за того, что сумма равномерно распределенных величин сама не является равномерно распределенной. А равномерность распределения результата в таких задачах обычно подразумевается.
Более подходящим с точки зрения распределения решением будет следующее: сгенерировать N-1
неубывающих равномерно распределенных случайных чисел в диапазоне [0, 1]
r1, r2, ..., rN-1
затем положить r0 = 0 и rN = 1 и в качестве искомых чисел взять попарные разности в соседях
r1 - r0, r2 - r1, r3 - r3, ..., rN - rN-1
На C++
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
unsigned N = 10;
std::vector<unsigned> r(N + 1);
r.front() = 0;
std::generate(r.begin() + 1, r.end() - 1, std::rand);
std::sort(r.begin() + 1, r.end() - 1);
r.back() = RAND_MAX;
for (unsigned i = 1; i <= N; ++i)
std::cout << double(r[i] - r[i - 1]) / RAND_MAX << " ";
std::cout << std::endl;
}
Одна из идей - создавать большие целые числа, а затем делить их, к примеру, на 1000. Так у Вас сформируется массив дробных чисел =) Действия выполняемых, пока сумма всех элементов не станет равной 1. Каждое сформированное число нужно проверить: подходит ли оно условию (должно быть меньше разности 1 и сумма остальных элементов массива).
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Рассмотрим простой класс:
я начинающий в c#Написана довольно большая консольная программа в ней множество раз получается массив методом system