Первоначально я собирался получить тот же ответ, что и все остальные, и связать его с проблемами с rand()
.Однако я подумал, что лучше сделать это, и вместо этого проанализировал распределение, которое фактически производит ваша математика.
TL; DR: шаблон, который вы видите, не имеет ничего общего с базовым генератором случайных чисел, а вместо этого просто связан сспособ, которым ваша программа манипулирует числами.
Я буду придерживаться вашей синей функции, поскольку все они похожи.
uint8_t blue(uint32_t x, uint32_t y) {
return (rand() % 2) ? (x + y) % rand() :
((x * y % 1024) % rand()) % 2 ? (x - y) % rand() :
rand();
}
Каждое значение пикселя выбирается из одной из трех функций: (x + y) % rand()
, (x - y) % rand()
и rand()
;
Давайте рассмотрим изображения, созданные каждым из них в отдельности.
Это то, что вы ожидаете, только шум.Назовите это «Изображение C»
Здесь вы добавляетепиксель координирует вместе и берет остаток от деления на случайное число.Если изображение 1024x1024, то сумма находится в диапазоне [0-2046].Случайное число, на которое вы ныряете, находится в диапазоне [0, RAND_MAX], где RAND_MAX составляет не менее 32 КБ, а в некоторых системах - 2 миллиарда.Другими словами, в лучшем случае есть шанс 1 к 16, что остаток не просто (x + y)
.Таким образом, по большей части эта функция будет просто создавать градиент увеличения синего в направлении + x + y.
Однако вы используете только младшие 8 бит, потому что вы возвращаете uint8_t
, так что выбудет иметь полосы градиентов шириной 256 пикселей.
Назовите это "Изображение A"
Здесь вы делаете что-то похожее, но с вычитанием.Пока х больше, чем у, у вас будет что-то похожее на предыдущее изображение.Но там, где y больше, результат - очень большое число, потому что x
и y
являются беззнаковыми (отрицательные результаты переносятся в верхнюю часть диапазона беззнакового типа), а затем включается % rand()
, и вы на самом делеполучить шум.
Назовите это «Изображение B»
Каждый пиксель в вашем окончательном изображении взят из одного из этих трех изображенийиспользуя функции rand() % 2
и ((x * y % 1024) % rand()) % 2
.Первый из них может быть прочитан как выбор с вероятностью 50% (игнорируя проблемы с rand()
и его младшими битами.)
Вот крупный план, где rand() % 2
является истинным (белые пиксели), поэтому изображение A
Вторая функция ((x * y % 1024) % rand()) % 2
снова имеет проблему, где rand()
обычно больше, чем то, что вы делите, (x * y % 1024)
, что не более 1023. Тогда (x*y%1024)%2
не дает 0 и 1 одинаково часто.Любое нечетное число, умноженное на любое четное число, является четным.Любое четное число, умноженное на любое четное число, также является четным.Только нечетное число, умноженное на нечетное число, является нечетным, и, таким образом, %2
для значений, которые являются четными тремя четвертями времени, даст 0 три четверти времени.
Вот крупный план, где ((x * y % 1024) % rand()) % 2
верно, чтобы изображение B можно было выбрать.Он выбирает точно, где обе координаты нечетные.
И вот крупный план того, где можно выбрать изображение C:
Наконец, объединяя условия, вот где выбрано изображение B:
И где изображение Cвыбрано:
Полученную комбинацию можно прочитать как:
С вероятностью 50% используйте пиксель из изображения A. Остальныевыберите время между изображениями B и C, где обе координаты нечетные, C, где любая из них четная.
Наконец, поскольку вы делаете то же самое для трех разных цветов, но с разными ориентациями,узоры ориентированы по-разному в каждом цвете и создают полосы или сетку, которые вы видите.