Условная рандомизация застряла
Первоначальный плакат здесь ...
У меня есть следующий код, чтобы рандомизировать значения примечаний и хранить их в массиве loop1[i]
, где i
- это конкретный шаг в цикле:
nextNote = random(-2, 3);
note = note + nextNote;
loop1[i] = note;
while (loop1[i] == loop1[i - 1] ||
loop1[i] == loop1[i - 2] ||
note > 6 ||
note < 0) {
nextNote = random(-2, 3);
note = note + nextNote;
loop1[i] = note;
}
(Я надеюсь, что это достаточно ясно).
Теперь он обычно работает до определенной точки, пока эскиз не наведет петли навсегда, чтобы рандомизировать разрешенный номер. Поэтому мои вопросы:
Запуск ATmega 2560, это на самом деле задача, слишком требовательная для процессора, или я должен подозревать, что она не работает должным образом?
Как я могу оптимизировать код, но сохранить вышеприведенные условия, чтобы избежать застревания петли?
3 ответа
Я думаю, что у вас проблемы с вашей математикой здесь, а не с вашим кодом. Какие вы симулируете очень похоже на одномерное случайное ходить . Согласно связанной странице MathWorld, для такого процесса «наиболее вероятное количество изменений знака в прогулке равно 0 ".
Если в какой-то момент вашей программы цикл начинается с note == 6
и
то он начинает беспорядочно подниматься, есть значительная вероятность для него
чтобы никогда не возвращаться к значениям ниже 7.
Изменить . Одним из возможных решений может быть избежать понятия случайной ходьбы и вместо этого повторять случайный выбор всегда из того же стартового точка.
int oldNote = note; // starting point
do
note = oldNote + random(-2, 3);
while (
note == loop1[i - 1] ||
note == loop1[i - 2] ||
note > 6 ||
note < 0);
loop1[i] = note;
Некоторые причины, по которым это не сработает:
-
Я чувствую, что
i
становится слишком большим, то есть он больше, чем длина используемого массива. Это может привести к сбоям или, по крайней мере, к непредсказуемым результатам. Вы можете легко проверить это, напечатав значениеi
(и отметьте максимальное значение). -
Я не вижу проблем с циклом while (хотя я бы использовал скобки вокруг
note > 6
и вокругnote < 0
, но я не думаю, что это действительно необходимо. -
Если значение становится ниже 0 или выше 6, все еще добавляются случайные значения, предположим, что значение равно +10 ... тогда для достижения этого значения может потребоваться много времени (если когда-либо) 6 снова. То же самое верно для значений <0. Может быть, вы никогда не должны допускать значения менее 0 и выше, чем 6, или делать случайные значения таким образом, что они имеют тенденцию идти к среднему (3).
Совет для отладки:
Однако самый простой способ отладить это - распечатать все соответствующие переменные (например, nextNote
, note
, i
, последние две заметки loop[i-2]
, loop[i-1]
и текущая заметка loop[i]
... Также напечатайте строку внутри цикла while, чтобы вы знали, когда ее пропускаете или нет. Вероятно, это даст вам достаточно информации, чтобы узнать, что не так.
Строка loop1[i] = note
не принадлежит к циклу (или над ним); вы не меняете i
в цикле, поэтому вы просто переписываете одно и то же место снова и снова.
Что касается самого цикла, какой вид использования у вас есть для этого и какой дистрибутив вы хотите? Ожидание, пока оно находится между 0 и 6, ужасно неэффективно. Вам нужно решить, какой дистрибутив вы хотите и реализовать его более непосредственно. Например, вы можете получить кусочно-квадратичное распределение, получив случайное число между нулем и sqrt (3), затем возведя в квадрат результат, а затем произвольно выбрав, следует ли вычесть результат из 6.