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

    +97

    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
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    program Project42;
    
    {$APPTYPE CONSOLE}
    
    uses
      SysUtils, Math;
    
    const
      Radix = 10;
    
    function čòũʼnť(N: Integer): Integer;
    begin
      Result := 0;
      while N > 0 do
      begin
        N := N div Radix;
        Inc(Result);
      end;
    end;
    
    function count(N: Integer): Integer;
    begin
    //  Result := Ceil(LogN(Radix, N));     { slow! }
      Result := Ceil(Log10(N));
    end;
    
    function rdtsc: Int64;
    asm
            rdtsc
    end;
    
    var
      I: Integer;
      t0: Int64;
    
    const
      N = 100500;
    
    begin
      try
        Assert((count(42) = čòũʼnť(42)) and (count(100500) = čòũʼnť(100500)));
    
        t0 := rdtsc;
        for I := 1 to N do
          čòũʼnť(Random(MaxInt + 1));
        Writeln('naïve: ', rdtsc - t0, ' ticks');
    
        t0 := rdtsc;
        for I := 1 to N do
          count(Random(MaxInt + 1));
        Writeln('prőper: ', rdtsc - t0, ' ticks');
    
        Writeln(StringOfChar('-', 42));
    
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    
      if DebugHook <> 0 then
      begin
        Write('any big key to exit...');
        Readln;
      end;
    
    end.
    
    { http://imgs.xkcd.com/comics/haiku_proof.png :-P }

    матан > метан
    O(1) > O(N)
    логарифм > байтоёбства с делением

    Запостил: bugmenot, 01 Декабря 2010

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

    • any big key to exit...
      WTF?
      Ответить
    • И зачем постить учебный тестовый пример? У меня таких тестов на разных языках десятки в ~/tests.

      К тому же, во-первых, не O(N), а O(log(N)) (можно сделать и O(log(log(N)))), во-вторых, иногда таки O(1) > O(log(N)).
      Ответить
      • это - пруф к дискуссии в http://govnokod.ru/4774#comment54761
        по копрометрической шкале Шайзе-Каковского в код попугайчик насрал, как минимум
        здесь N -- кол-во [десятичных] разрядов, не абсолютная величина, чтобы не морочить себе голову с основанием логарифма
        Ответить
        • От вас развернутый ответ вообще можно услышать без "больших" и "маленьких" пальцев, а также медленных констант ?
          Ответить
          • Товарищ пытается сказать, что алгоритм со сложностью O(1) лучше алгоритма со сложностью O(N).
            Потому что константное время лучше, чем время, зависящее от данных.
            Ответить
            • У нас N ограничено (<=10), так что O(N) внезапно превращается в O(1).
              Ответить
            • В общем случае да. Но случай скорее частный получается.
              Ответить
        • Для 32-битных чисел имеем максимум 10 целочисленных делений (можно деление заменить умножением, можно вообще оптимизировать к четырём целочисленным сравнениям). Против преобразования в double, логарифма, округления, преобразования к целому.

          Для 64 бит логарифм может просто не работать.
          Ответить
          • ORLY? После минимума правки оба варианта будут работать с 19 десятичными разрядами. Что значит может?
            Ответить
            • OH, SHI BB code fail
              ORLY? После минимума правки оба варианта будут работать с 19 десятичными разрядами. Что значит "может"?
              Ответить
              • В 64-битном int больше значащих бит, чем в мантиссе 64-битного double. 9999999999999999999 и 10000000000000000000 неразличимы.
                Ответить
                • всё это имело бы смысл, если бы 8087 не использовал 64 бита под мантиссу и 15 под характеристику
                  (как известно, дельфи прибит гвоздями к интелу)
                  Ответить
                  • Это проблемы Делфи. Есть другие процессоры и другие языки.

                    У log10 в сигнатуре real, double или extended (или как оно там обзываются)? Потеря точности тут.

                    Только что заметил грубую ошибку -- count(9)=1.
                    Ответить
                    • Т.е. ошибка в том, что count(9)=count(10)=1.
                      Ответить
                      • Ну вот, а говорил: код - не говно :-D
                        Extended, естественно, так что в мантиссу влезет

                        ~1100 тактов занимает 19 раз 2^63-1 поделить на 10
                        Ответить
                        • Ну, я попробовал (http://pastie.org/1341599), с логарифмом получается 150-175 нс на вызов, из них 25-50 нс -- на рандом. Разнообразные варианты без логарифма -- за те же 25-50 нс.
                          Ответить
                          • Фу, ёлочки...
                            else if пишется на одной строке.
                            Ответить
                            • Это if разного уровня.

                              Не ёлочка, а баобаб. ;) Почти сбалансированное дерево.
                              Ответить
                              • Ну и что, что разного? Всё равно лучше в 1 строчку написать, например тут:
                                if( n < 1000)return 3
                                else if(n < 10000)return 4
                                else return 5;
                                Ответить
                                • Не могу согласиться.
                                  Ответить
                                  • Ну и лепи свои ёлочки. Код говнисто смотрится. И вообще, ёлочки сюда (на этот сайт) попадали не раз.
                                    Ответить
                                • Тоже так считаю.

                                  else if - это как в других языка готовая конструкция elsif!
                                  Ответить
    • И какие ваши результаты ?
      Ответить
    • а что за выпендреж в 41ой?
      Ответить
    • не ожидал, вот что значит проверять!
      Ответить
    • čòũʼnť - говно

      почему Random(MaxInt + 1)? давайте, чтоб было одинаково.
      Ответить
      • > čòũʼnť - говно
        вот именно, ч.т.д. :-)

        не понял, где неодинаково? +1 чтобы покрыть весь диапазон неотрицательных целых [0,MaxInt], а не [0,MaxInt)
        Ответить
        • И чему же равно MaxInt + 1?
          Ответить
        • ну рандомные числа проверяются и там, и там.
          в первом случае могут одни попасться, во втором — другие.


          P.S Посмотрел щас, здесь 100500 вариантов, так что может и не надо.
          Ответить
          • теперь понятно, что я имел в виду?
            Ответить
            • так и задумывалось, статистическая оценка вместо перебора
              Ответить
      • нако
        template<const size_t base, const size_t value>
        struct log_ {
        	enum { result = 1 + log_<base, value / base>::result };
        };
        
        template<const size_t base>
        struct log_<base, 0> {
        	enum { result = 0 };
        };
        
        int main(int, char *[]) { std::cout << log_<10, 19001>::result << std::endl; return 0; }
        Ответить
        • Функциональное программирование на стадии компиляции?
          Да, мне этого в Дельфях не хватает иногда...
          Ответить
          • дельфях еще СТЛ нет. завязывал бы ты с "учебными языками"
            Ответить
            • А ещё в дельфовых программах нету в 15 раз большей плотности ошибок. Завязывал бы ты говно ебать.
              Ответить
              • >>А ещё в дельфовых программах нету в 15 раз большей плотности ошибок.
                можно пруф?
                Ответить
                • http://www.xakep.ru/post/38388/default.asp?print=true

                  Только там не в 15, а в 16 раз.
                  Вообще, хороший пример - ТеХ, автор которого, в отличие от Билли сам ПЛАТИЛ пользователям за обнаруженные ошибки.

                  Да да да, я знаю, это всё упоротые пасквилянты по ссылке развлекаются.
                  Ответить
                  • я не очень понял -- кем было обнаружено?
                    студентом, который пишет для журнала "хакер"?

                    я совершенно не паскалефоб (из всех языков я только VB и php нелюблю, может javascript еще), просто при таком количестве кода и написанных на нем операционках -- си смешно хоронить)
                    да и прикладная разработка (которая безусловно уходит от си) идет явно не к дельфи))
                    Ответить
                    • Я не про общий смысл, но про плотность ошибок очень похоже на правду.
                      Но вообще лучше бы си не рождался - его распространение связано скорее с интеллектуальным онанизмом (зацените, на каком крутом языке я прогу написал), чем с практической полезностью.
                      Ответить
                      • а) ну в целом да
                        паскаль более жесток в типизации, а следовательно налажать в нем в сложнее.

                        распостранение си связано с тем, что на нем написаны самые популярные оси))
                        Ответить
                        • Вот и я о том.
                          По надёжности уберСи сливает недоПаскалю, и ничего с этим не сделать.
                          Говноёбы вот вообще паскаль не осилили (у них до сих пор его упоминание вызывает боль), они любят си ебать. Логично.
                          Ответить
                          • надежность это не основное)
                            стройность и логичность паскаля дает ему плюсы при обучении (не даром он считается лучшим языком для обучения), но на практике эта стройность может быть и не нужна (Вам же не нужен GC). Человек, который 15 лет писал на сях скорее всего будет на них нормально писать, даже несмотря на все изъяны).
                            Ответить
                            • GC в принципе не нужен. Чтобы в языке с автовызовом деструктора сделать утечку, надо сознательно делать фигню с указателями. Ну так и в ГЦ-языках тоже можно сделать утечку, если захотеть или если быть мудаком.
                              Ответить
                  • > В хаосе последних 10-15 лет проявилась ещё более тревожная
                    > и опасная тенденция: распространение C-образных языков.
                    Ахаха, автора, автора на сцену!
                    Ответить
                    • он занят.
                      у него сегодня 5 уроков.

                      зы: хакер -- это правильный журнал для чтения конечно
                      Ответить
                  • О, да. Напоминает старый текст "СЕНСАЦИЯ: Создатели Cи и UNIX признают, что разыграли весь мир!".
                    Верить серьёзному аналитическому журналу? Да, конечно, там ведь не обманывают своих малолетних читателей.
                    Ответить
                    • Я тоже считаю, что 16 раз - это передёргивание. Поэтому я написал более осторожную оценку: в 15 раз.
                      Ответить
                    • напоминает исследования от microsoft: "мы выяснили, что поддержка windows стоит в среднем в 25 раз дешевле поддержки linux, а программы на .net на 80% быстрее программ на java"
                      Ответить
            • дельфях уже СТЛ нет
              Ответить
    • rdtsc это таймер у пней?
      а паскаль -- что бы паскалефобов позлить?

      Пока N махонькое -- O(N) может быть даже быстрее O(1). Потом N вырастет и сюрприз-сюрприз. Ваш КО.
      Ответить
      • счетчик тактов

        логарифм медленнее чем X делений, найти X, заморока же
        Ответить
      • Буду холиворить. Это не Паскаль. В Паскале нет исключений — они взяты из языка программирования Ада. В Паскале нет модулей — они взяты из языка Модула. Надо подумать, что это... А, вспомнил, это же Object Pascal в реализации Borland, известный, как Delphi. Странным образом совпало с названием раздела. К чему бы это?
        Ответить
        • буду КО.
          я имел ввиду не ванильный паскаль, а тот, что делал борланд и называл его турбо паскалем (или борланд, в более полной версии).

          >> В Паскале нет модулей — они взяты из языка Модула
          погодите, в классическом паскале нет модулей? Тоесть вся программа -- один модуль?

          зы: я имел ввиду -- зачем багминот свой пример именно на паскале написал
          Ответить
          • http://www.standardpascal.com/iso7185.html
            Нету там ничего, кроме Program. Получается, что одна программа — один модуль.
            В Турбо Паскале до четвёртой версии не было модулей (но, кажется, можно было прилинковывать обжи), зато можно было получать ортодоксальный com-файл. А для TP 4.0, в котором появились-таки модули, энтузиасты уже написали TPU2OBJ.
            Ответить
            • шото я не понял.
              а как же мне код реюзать?
              иклудить его в момент компиляции и компилировать каждый раз?

              и никакого аналога runtime lib нет?
              а всякие writeln откуда берутся?
              Ответить
              • {$L writeln.obj}
                типа того
                Ответить
              • Никак. Инклюд и подключение скомпилированных объектников -- это нестандартные расширения Турбо Паскаля. См. исходники ТеХа, после препроцессинга это один файл мегабайта на полотора.

                writeln и проч. встроены в язык. Это у Си такое новшество было -- что все стандартные функции вынесены в библиотеки.
                Ответить
                • хм)
                  мне казалось что линковка -- святое дело в любом языке
                  оказывается -- нет)))

                  спасибо.
                  Ответить
                  • Паскаль вообще в байт-код компилировал, типа явы или питона. Турбо -- значит быстрый, оттого, что компилировал прямо в машинный код.
                    Ответить
              • труъ Паскаль таким и был примитивным, а _встроенные_ процедуры были как бы встроены
                Ответить
          • Хороший вопрос, почему употребление Паскаля вызывает холивары, так же, как упоминание любимой ОС или любимого браузера на любом форуме.
            Ответить
          • re: зачем -- начем же еще изображать матан как не на паскале? оператор
            :=
            винрарен
            Ответить
            • )))да. язык настоящих преподавателей из ВУЗа) кстати, книжечка Вирта на нем)
              про стуктуры и алгоритмы
              Ответить
            • := - обыкновенная халтура гражданина Вирта, чтобы упростить КА для распознавания грамматики языка

              собственно Вирт и создал паскаль, и как бээ логично, что в своих книгах, он его юзает пропагандирует
              Ответить
              • := это математический знак присваивания, который вполне логично смотрится и в Паскале. А вот = в качестве присваивания - это большое зло, потому что, во-первых, строчка i=i+1 с непривычки взрывает мозг намного сильнее, чем i:=i+1, а во-вторых, легко лажануться и написать if (i=1) вместо if (i==1).

                == - обыкновенная халтура языка Си, которой нет среди математических обозначений и которая призвана что-то придумать для оператора сравнения, когда = уже занято.
                Ответить
                • >>о-вторых, легко лажануться и написать if (i=1) вместо if (i==1).
                  и словить варнинг
                  нет?
                  Ответить
                  • Ну хорошо, что появились компиляторы с предупреждениями.
                    А если мне действительно надо написать if (i=j)?
                    Отрубать предупреждения?
                    Вот если я напишу if (i:=j) то тут всё понятно.
                    Ответить
                    • >А если мне действительно надо написать if (i=j)?
                      Нефиг такое писать в if'е. А если и требуется присваивание, то и сравнение какое-то присутствует. Например:
                      if( (i=f()) < 0) { ... }
                      Ответить
                      • i и j - типа боолеан.
                        То есть (i:=j) уже имеет булев типа.

                        > Нефиг такое писать в if'е.

                        Давно бы запретили.
                        Ответить
                        • >i и j - типа боолеан.
                          Тогда добавить явную булеву константу:
                          if( (i=j) == true )

                          Вот тут уже ==true как бы и не ГК, как в большинстве случаев.
                          Ответить
                          • ФФФФУУУУУУУ
                            Ответить
                            • "ФУ" началось раньше, с желания присваивать "боолеан'ы" в if'e
                              Ответить
                          • >>Вот тут уже ==true как бы и не ГК, как в большинстве случаев.
                            здраствуй похупэ со его $a === true
                            Ответить
                            • Выглядит необычно. Тем не менее - корректный способ подавить warning'и. И для читающего код сразу ясно, что присвоение в условии - это не бага, а фича.
                              Не нравится ==true ? напиши >false :)
                              Ответить
                              • В некоторых языках программирования false=0, true=-1. ;)
                                Ответить
                                • Там, где нет явного bool - может быть и так. В С++ же прописано в стандарте, что false<true.
                                  Ответить
                                • это - слаботипизированное утверждение :)
                                  Ответить
                • мутабельные проблемы
                  let f a = if a = lol then problem_officer? else mutable_rooster
                  Ответить
              • Ему ничего не стоило сделать обычное равно.
                Читайте как делаются компиляторы.
                Ответить
              • := и =
                = и ==
                ==============
                Первый схалтурил, вторые — нет.
                Офигенная разница.
                Ответить
              • ВНЕЗАПНО! В языке METAFONT Дональда Кнута есть и := , и =
                := означает «присвоить», как и в Паскале.
                = означает «решить уравнение», как в функциональных языках. Да, в метафонте есть специальное значение переменной «не определено», относительно такой переменной уравнение и решается.
                Ответить
        • Генерал Очевидность! :-)
          Ответить
    • MaxInt + 1 отказалось компилиться.
      У меня логарифм оказался быстрее деления, в полтора раза.
      Ответить
      • пресловутая Delphi 7 небось :-)
        ага, примерно так и есть (сильно зависит от твиков при сборке, но добро матан всегда побеждает)
        Ответить
        • аналогично, специально проверил.
          для семизнаков быстрее деление, для восьмизнаков - логарифм.
          кстати, для отрицательных чисел и 0 не работает, но, видимо, оно и не требуется.
          Ответить
          • Кстати, да, random(MaxInt) скорее всего будет из 8 знаков, а типичное число, встречающееся в работе - намного меньше.
            А ещё рандом тоже время неплохо кушает.
            Ответить
            • туше, есть такой изьян в исследовании
              Ответить
            • Да, 90% чисел меньше миллиарда будут 9-значными. 9% 8-значными и т.д. В жизни обычно встречаются числа короче.

              Всё ждал, заметит ли кто.
              Ответить
          • по аналогии с машинным эпсилон - машинная тьма
            Ответить
    • http://pastie.org/1341599

      Логарифм в 2-5 раз медленнее при полной оптимизации. Если вычесть время на рандом -- вообще на порядок.
      Ответить
      • может мой вариант тоже сравнишь? http://www.govnokod.ru/4805#comment55233

        хехе
        Ответить
        • Нужна ещё генерация шаблонами 10000000 вызовов для псевдослучайных чисел. Вот как всё это докомпилируется -- сравню. Если ещё жив буду.
          Ответить

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