- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
struct Point
{
double x,y,z;
Point()
{
L1:
x=Rand();
y=Rand();
z=Rand();
double r=sqrt(x*x+y*y+z*z);
if(r<eps)
goto L1;
x/=r;
y/=r;
z/=r;
}
...
};
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
+65.3
struct Point
{
double x,y,z;
Point()
{
L1:
x=Rand();
y=Rand();
z=Rand();
double r=sqrt(x*x+y*y+z*z);
if(r<eps)
goto L1;
x/=r;
y/=r;
z/=r;
}
...
};
Можно добавить сомнительное поведение конструктора по-умолчанию, и кривой алгоритм.
Используя тот факт, что самописный Rand() в этом проекте возвращает число от -1 до 1. Кстати, реализация -- отдельная фиерия, может даже стоит выложить еще одним говнокодом...
Или даже, дабы устранить неявности,
p.x = r*Rand();
p.y = r*Rand();
p.z = sqrt(r*r - x*x - y*y);
тогда r можно менять, или передать параметром
Заметь, здесь нет циклов вообще: ни через do-while, ни через goto.
ежу понятно, что r*r - x*x - y*y может запросто быть отрицательным числом.
А, и да. Оно возвращает даббл между -1 и 1 еще. Вот, наслаждайтесь:
Вот вариант получше, к тому же равномерно распределяющий точку по поверхности сферы:
Да и тормозов никаких не будет. С SSE2 что синус, что косинус вычисляется меньше, чем за 100 тактов, не уверен, что рандом сильно быстрее, или что конструирование объекта сильно быстрее, или что алгоритм, которому понадобилось кидать рандомные точки, сильно быстрее. В конце концов, алгоритм может банально быстрее сойтись на качественных начальных точках.
Подсказка - посмотри, что получается в плоскости YZ.
Проецируя точку, равномерно распределённую на отрезке, на полуокружность, мы не получим равномерного распределения.
1)goto.
2)Это вектор, а назвали point(точка).
3)Сдесь конструктор по умолчанию пытаеться получить значения случайного нормированного вектора.
4)Алгоритм может зациклиться во время полной луны в полночь или ещё когда-нибудь .
5)if(r<eps) - у меня есть подозрения, что на границе точности эпсилиона уже будет невозможно сравнивать и мы или получим исключение или получем не верное значение.
6)Оно точно поделиться, если когда условие r=eps? Тут или мы получим бредовое значение или исключение.
п.2 У вектора нет радиуса точки назначения (r). ;-) Здесь сфера с указанием на нее единичного вектора.
п.3 см п.2
п.4 - а можно поразвернутее? В каких именно случаях? r/eps - вроде решает проблему?
п.5, п.6 - В том то и дело, что eps восприниматься однозначно. Мы получим единичный вектор. Проверьте ;-)
P.S. Хотя я назвал вектора единичными, их скорее стоило именовать базовыми. Воть... Теперь все.
п.2, п.3 - ты правильно сказал. :-)
p.x = Rand();
p.y = Rand();
p.z = sqrt(r*r - x*x - y*y);
Почему?
Во-первых, если и x и y вдруг окажутся близки к единице, то нам придётся извлекать корень из отрицательного числа.
А ещё, потому что вместо случайной точки, равномерно распределённой по сфере (нам ведь это надо?) имеем проекцию на полусферу точки, равномерно распределённой по... квадрату?
То есть координату z можно взять как просто рандом.
Далее, берём случайное число, равномерно распределённое на отрезке от -п до п, получая аргумент проекции нужной точки на плоскость XY.
Вот так где-то:
p.z = Rand();
r = sqrt(1-sqr(p.z));
arg = Pi*Rand();
p.x = r*cos(arg);
p.y = r*sin(arg);
Тогда так (чтобы без цикла, и чтобы делалось ровно то же, что в исходном коде): случайный вектор из куба по направлению распределён так же, как случайный вектор на поверхности куба. То есть сначала можно взять случайное число от 1 до 6, потом - случайную точку в квадрате, потом, в зависимости от случая, клеить её на соответствующую сторону и делить.
Ой ли? Где про это можно почитать?
Это с чего вдруг?
Есть одна маленькая просьба: тервер расписывать более формально.