1. C++ / Говнокод #2365

    +65.3

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 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;
    	}
    
    	...
    };

    Запостил: brainiac, 03 Января 2010

    Комментарии (42) RSS

    • Метки вместо цикла с пост-условием? Говнокод не защитан.
      Ответить
      • Использование goto там, где в нем совершенно нет необходимости, что если не это считать говнокодом?
        Ответить
        • Очень низкая концентрация говна. Вот если бы меток было пять-шесть...
          Ответить
          • Ну, не все говно так очевидно...
            Можно добавить сомнительное поведение конструктора по-умолчанию, и кривой алгоритм.
            Ответить
            • Можно пример вашего аналогичного кода (при условии, что понимаете задачу)?
              Ответить
              • class Point
                {
                public:
                	Point() : x(0.0), y(0.0), z(0.0) {}
                	
                	static Point RandomPoint()
                	{
                		Point p;
                		double r = 1.0;
                		p.x = Rand();
                		p.y = Rand();
                		p.z = sqrt(r*r - x*x - y*y);
                		return p;
                	}
                
                	...
                
                private:
                	double x, y, z;
                };


                Используя тот факт, что самописный Rand() в этом проекте возвращает число от -1 до 1. Кстати, реализация -- отдельная фиерия, может даже стоит выложить еще одним говнокодом...
                Ответить
                • Там, само собой, p.z = sqrt(r*r - p.x*p.x - p.y*p.y);
                  Или даже, дабы устранить неявности,
                  p.x = r*Rand();
                  p.y = r*Rand();
                  p.z = sqrt(r*r - x*x - y*y);
                  тогда r можно менять, или передать параметром
                  Ответить
                  • Стоп, про передаваемый r - ничего не сказано, и про то что его нужно менять. Это конечно не значит, что условия задачи не поменяются и r не нужно будет предопределять в будущем. Всего кода мы не видим, а если исходить из того, что автор таки знает что делает? Тогда никакого говнокода...
                    Ответить
                    • Писать класс точки, которая умеет рандомно кинуть себя на единичную сферу -- бессмысленно. Пусть точка остается нормальной точкой и предоставит удобный интерфейс по работе с собой. Удержать ее на единичной сфере -- задача алгоритма, ее использующего.
                      Ответить
                    • Ну вот тебе без явного r.
                      class Point
                      {
                      public:
                      	Point() : x(0.0), y(0.0), z(0.0) {}
                      	
                      	static Point RandomPoint()
                      	{
                      		Point p;
                      		p.x = Rand();
                      		p.y = Rand();
                      		p.z = sqrt(1.0 - x*x - y*y);
                      		return p;
                      	}
                      
                      	...
                      
                      private:
                      	double x, y, z;
                      };


                      Заметь, здесь нет циклов вообще: ни через do-while, ни через goto.
                      Ответить
                      • Заметь, я и предложил без циклов (залогиниться с ноута забыл только :) )
                        Ответить
                        • И, кстати, не стоит писать код в 5 утра, видимо, так как лажа получилась дикая, на единичную окружность оно не попадает, да и легко отрицательное число под корнем обрести =)
                          Ответить
                  • Вы, ребята, фанаты комплексных чисел...
                    ежу понятно, что r*r - x*x - y*y может запросто быть отрицательным числом.
                    Ответить
                • А rand стандартный то чем не угодил? Зачем было переписывать?
                  Ответить
                  • Ну я даже не знаю... Наверное, слишком мало уникальных значений -- жалкие RAND_MAX + 1.
                    А, и да. Оно возвращает даббл между -1 и 1 еще. Вот, наслаждайтесь:
                    double Rand()
                    {
                    	long long rnd=(long long)rand()*(RAND_MAX+1)*(RAND_MAX+1)+rand()*(RAND_MAX+1)+rand();
                    	if(rand()&1)
                    		rnd=-rnd;
                    	return (double)rnd/((double)RAND_MAX*(RAND_MAX+1)*(RAND_MAX+1)+RAND_MAX*(RAND_MAX+1)+RAND_MAX);
                    }
                    Ответить
                • Ага. Особенно хорошо себя поведет sqrt(1.0-1.0-1.0). Удачи, говнокодер.
                  Ответить
                  • +1
                    Ответить
                  • Да, очень ценный коммент. Как уже писалось выше, код рожден в 5 утра, поэтому и лажа.
                    Вот вариант получше, к тому же равномерно распределяющий точку по поверхности сферы:
                    z = -1 + 2*((double)rand())/RAND_MAX;
                    alpha = 2*pi*((double)rand())/RAND_MAX;
                    r = sqrt(1.0 - z*z);
                    x = r*cos(alpha);
                    y = r*sin(alpha);
                    Ответить
                    • Да, так правильно. Опередил ты меня.
                      Ответить
                    • Тригонометрия == тормоза. Причём гарантированные тормоза, а не гипотетические зацикливание в исходном говнокоде.
                      Ответить
                      • Ну тригонометрия тут, как минимум, для того, чтобы получить равномерное распределение точки по сфере.
                        Да и тормозов никаких не будет. С SSE2 что синус, что косинус вычисляется меньше, чем за 100 тактов, не уверен, что рандом сильно быстрее, или что конструирование объекта сильно быстрее, или что алгоритм, которому понадобилось кидать рандомные точки, сильно быстрее. В конце концов, алгоритм может банально быстрее сойтись на качественных начальных точках.
                        Ответить
                  • Ой, ну ладно
                    class Point
                    {
                    public:
                    	Point() : x(0.0), y(0.0), z(0.0) {}
                    	
                    	static Point RandomPoint()
                    	{
                    		Point p;
                    		p.x = Rand();
                    		p.y = sqrt(1.0-x*x)*Rand();
                    		p.z = sqrt(1.0 - x*x - y*y);
                    		return p;
                    	}
                    
                    	...
                    
                    private:
                    	double x, y, z;
                    };
                    Ответить
                    • Нет, не ладно. Так равномерного распределения мы не получим.
                      Подсказка - посмотри, что получается в плоскости YZ.
                      Проецируя точку, равномерно распределённую на отрезке, на полуокружность, мы не получим равномерного распределения.
                      Ответить
          • Одной метки достаточно, что-бы считать это говнокодом.
            Ответить
            • Кроме вбитой в моск "истины", что любая метка плохой стиль, ничего содержательного.
              Ответить
              • Я вот, например, эту метку, из-за ее расположения, не заметил пока не прочитал goto. Мне пришлось внимательнее изучпть код, чтобы понять что он делает.
                Ответить
    • Еёёё... Ну и говно.
      1)goto.
      2)Это вектор, а назвали point(точка).
      3)Сдесь конструктор по умолчанию пытаеться получить значения случайного нормированного вектора.
      4)Алгоритм может зациклиться во время полной луны в полночь или ещё когда-нибудь .
      5)if(r<eps) - у меня есть подозрения, что на границе точности эпсилиона уже будет невозможно сравнивать и мы или получим исключение или получем не верное значение.
      6)Оно точно поделиться, если когда условие r=eps? Тут или мы получим бредовое значение или исключение.
      Ответить
      • п.1 - догма, растянутые на х.з. сколько страниц вложенные циклы, например, заебывают не хуже меток. Метка в пределах максимальной видимость, т.е. пофиг, что использовать.
        п.2 У вектора нет радиуса точки назначения (r). ;-) Здесь сфера с указанием на нее единичного вектора.
        п.3 см п.2
        п.4 - а можно поразвернутее? В каких именно случаях? r/eps - вроде решает проблему?
        п.5, п.6 - В том то и дело, что eps восприниматься однозначно. Мы получим единичный вектор. Проверьте ;-)

        P.S. Хотя я назвал вектора единичными, их скорее стоило именовать базовыми. Воть... Теперь все.
        Ответить
        • Отвечаю сам себе же, ибо пьян... :-)

          п.2, п.3 - ты правильно сказал. :-)
          Ответить
        • 4й пункт: не знаем, что за рандом успользуется. Вдруг он честный и сможет выдать произвольно длинную последовательность достаточно малых значений?
          Ответить
    • Минус балл за

      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, потом - случайную точку в квадрате, потом, в зависимости от случая, клеить её на соответствующую сторону и делить.
            Ответить
            • Да. Но я думаю, что автор все же подразумевал равномерное распределение по сфере.
              Ответить
            • >случайный вектор из куба по направлению распределён так же, как случайный вектор на поверхности куба

              Ой ли? Где про это можно почитать?
              Ответить
              • А это не очевидно? Куб состоит из концентрических кубов. Функция распределения точки из куба по направлению - это интеграл функции распределения точки из слоя. Интеграл по слою. Для каждого слоя функция одна и та же. Усё.
                Ответить
                • >Функция распределения точки из куба по направлению - это интеграл функции распределения точки из слоя.

                  Это с чего вдруг?
                  Есть одна маленькая просьба: тервер расписывать более формально.
                  Ответить
    • Тут нечго думать над алгоритмом, хотя он действительно крив. Одно только применение конструктора по умолчанию для генерации случайных значений - говнокод. Если уж твердо решили использовать это в конструкторе, то хоть класс назвали бы соответственно, например RandomPoint или ещё как-нибудь, а не просто Point.
      Ответить
    • Использовать struct вместо class + public - не рекомендуеться.
      Ответить

    Добавить комментарий