1. Pascal / Говнокод #17020

    +140

    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
    20. 20
    21. 21
    type func = function (x : real) : real;
    const
    	eps = 0.0000003;
    	pi = 3.14159265358979;
    function Integral (f : func; a, b : real) : real;
    var center : real;
    begin
    	center := (a + b) / 2;
    	if abs(b - a) < eps then
    		Integral := f(center) * (b - a)
    	else Integral := Integral(f, a, center) + 
    		Integral(f, center, b);
    end;
    function myFunc(x : real) : real;
    begin
    	myFunc := cos(x) / x;
    end;
    begin
    	writeln(Integral(myFunc, pi/2, pi));
    	readln;
    end.

    Толи я дурачек, толи автор кода - школьник....

    Запостил: ShadowXX, 02 Ноября 2014

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

    • За readln в конце программы предлагаю устраивать показательные казни.
      Ответить
      • Равно как и за system("pause") или getch() в конце сишной проги.
        Ответить
        • для лаб, запускаемых не из консоли, самое то.
          Ответить
          • > запускаемых не из консоли
            Нехуй. Пускай запускают коконсольные проги как положено.
            Ответить
            • Они ж вроде до сих пор из синей среды запускают, не?Я конечно плюсанул, но вот такой осадочек, что сам давным-давно так писал, остаётся.
              Ответить
              • В синей среде можно нажать F5 и посмотреть результаты последнего запуска.
                Ответить
              • Хуже всего, что так писать заставляют преподы. А ещё они заставляют чистить консоль, причём не в конце срания, а непосредственно после того, как программа запустится. Говорят, что иначе воняет сильно.
                Ответить
                • > заставляют чистить консоль
                  > Говорят, что иначе воняет сильно.
                  По-моему, это наоборот хорошо: сразу видно, что вывела программа именно сейчас, а не три запуска назад, когда студент ещё не исправил баг.
                  Пожалейте преподавателей. И так постоянно надо переключать контекст, а Вы ещё и логи фильтровать заставляете.

                  Тут как раз можно плавно и естественно подвести к дебаг/релиз версиям . В c/c++ можно сразу писать
                  #ifdef _DEBUG 
                  system("cls");
                  #endif
                  Ответить
                  • А в остальных языках еще проще - можно просто одну строчку закомментировать\раскомментировать.
                    Ответить
                    • Хотел возразить, но для лаб - да, пойдёт :)

                      P.S. Что-то внезапно решил проверить комментарии на ГК. Открыл страницу за несколько секунд до того, как пришло письмо.
                      Ответить
    • > Толи
      > дурачек

      Нет, я подозреваю, что вы и есть школьник. Ещё не дошли до тех классов, в которых проходят правописание частиц и о-ё после шипящих.
      Ответить
    • а что не так с кодом?
      Ответить
      • Пирфоманс.

        Подсказка: (pi - pi/2) / 0.0000003 = 5 мильонов.
        Ответить
        • ну может в натуре 5 мильонов точек надо, откуда мне знать
          Ответить
          • > Integral := Integral(f, a, center) + Integral(f, center, b);

            Каждый такой вызов сохраняет в стеке 2 × (адрес возврата + значение (E)BP + три параметра вызова + локальную переменную center).

            Если лабы пишут по старинке в 16-битном ТП, то у нас в стеке максимум 64 килобайта. Вызов функции Integral сожрёт 4 + 2 + (4 + 6 + 6) + 6 = 28 байт (хотя я не помню, выравнивается ли real, нужно сконпелировать и проверить). Стека хватит на какую-то жалкую тысячу точек, но не на миллионы.
            Ответить
            • > Стека хватит
              Да, стека хватит. Глубина рекурсии будет всего 22-23.
              Ответить
              • Проверим. Код:
                type func = function (x : real) : real;
                const
                	eps = 0.0000003;
                var
                	sp: word;
                const	
                	minsp: word = $FFFF;
                	maxsp: word = 0;
                function Integral (f : func; a, b : real) : real;
                var center : real;
                begin
                	asm
                	  mov [&sp], sp
                	end;
                	if sp < minsp then minsp := sp;
                	if sp > maxsp then maxsp := sp;
                	center := (a + b) / 2;
                	if abs(b - a) < eps then
                		Integral := f(center) * (b - a)
                	else Integral := Integral(f, a, center) + 
                		Integral(f, center, b);
                end;
                function myFunc(x : real) : real; far;
                begin
                	myFunc := cos(x) / x;
                end;
                begin
                	writeln(Integral(myFunc, pi/2, pi));
                	writeln('Stack usage: ', maxsp - minsp);
                end.


                Выхлоп:
                -3.9833273940E-01
                Stack usage: 874


                Ну да, стека действительно хватает. Что-то я разбежался...
                Ответить
            • тут логарифмическая зависимость глубины от числа точек, так что должно хватить
              Ответить
              • Принято.

                Но в любом случае здесь много ненужных прыжков и умножений. Тормозить же будет.
                Ответить
                • Такая бинарная схема сразу даёт примерный результат и на ходу повышает точность, это позволяет с небольшими доработками сделать так, чтобы на каждом участке бралось столько точек, сколько нужно (ну типа взять ещё пару точек и сравнить значение в первой и полусумму других двух и если разница невелика, то не рекурсировать).
                  А ты видимо предлагаешь тупо взять ЭН равномерно взятых точек и тупо сложить, но "простая" схема не позволяет вовремя остановиться, эн надо взять заренее. А ещё "простая" схема уязвима для плавающего питуха, потому что когда ты будет прибавлять последний эпсилон к миллионной сумме предыдущих чисел, то у тебя будет ну ты понел.
                  Ответить
                  • У той самой схемы с оценкой точности условие для прекращения итераций abs(интеграл - интеграл_на_предыдущем_шаге) < eps, а тут автор останавливается по abs(b - a) < eps, т. е. он именно берёт эн заранее и никак не оценивает точность. В том и говно.
                    Ответить
                    • Да, он эту фичу не использует, но считай это заделом на будущее.
                      По-прежнему в силе защита от плавающего питуха.
                      Ответить
                      • Vanished
                        Ответить
                      • Соглашусь. Здесь складываются числа, близкие по величине, так что проблем с машинным эпсилон не будет. Хотя бы это можно считать достоинством кода.
                        Ответить
                      • Комментарий удалён шариатским судом.
                        Ответить
                      • А вообще для того, чтобы бороться с плавающим питухом, слагаемые нужно сортировать и начинать суммирование с наименьшего по величине. Но для миллионов слагаемых это будет жутко медленно...
                        Ответить
                        • > и начинать суммирование с наименьшего по величине
                          используя два сумматора
                          Ответить
                        • угу, причём новую сумму втраивать в текущий массив, и на каждом шаге вновь брать два наименьших
                          короче. такой рекурсией проще и не намного менее надёжно
                          Ответить
    • Комментарий удалён службой безопасности Ирландской Повстанческой Армии.
      Ответить
    • Руслана он застал в холле, как всегда, колдующим у плиты. Только на этот раз он не танцевал, а при появлении Вита лишь бросил короткое "привет".
      Ответить

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