1. Java / Говнокод #26791

    +1

    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
    69. 69
    70. 70
    package literatePrimes;
    
    import java.util.ArrayList;
    
    public class PrimeGenerator {
      private static int[] primes;
      private static ArrayList<Integer> multiplesOfPrimeFactors;
    
      protected static int[] generate(int n) {
        primes = new int[n];
        multiplesOfPrimeFactors = new ArrayList<Integer>();
        set2AsFirstPrime();
        checkOddNumbersForSubsequentPrimes();
        return primes;
      }
    
      private static void set2AsFirstPrime() {
        primes[0] = 2;
        multiplesOfPrimeFactors.add(2);
      }
    
      private static void checkOddNumbersForSubsequentPrimes() {
        int primeIndex = 1;
        for (int candidate = 3;
             primeIndex < primes.length;
             candidate += 2) {
          if (isPrime(candidate))
            primes[primeIndex++] = candidate;
        }
      }
    
      private static boolean isPrime(int candidate) {
        if (isLeastRelevantMultipleOfNextLargerPrimeFactor(candidate)) {
          multiplesOfPrimeFactors.add(candidate);
          return false;
        }
        return isNotMultipleOfAnyPreviousPrimeFactor(candidate);
      }
    
      private static boolean
      isLeastRelevantMultipleOfNextLargerPrimeFactor(int candidate) {
        int nextLargerPrimeFactor = primes[multiplesOfPrimeFactors.size()];
        int leastRelevantMultiple = nextLargerPrimeFactor * nextLargerPrimeFactor;
        return candidate == leastRelevantMultiple;
      }
    
      private static boolean
      isNotMultipleOfAnyPreviousPrimeFactor(int candidate) {
        for (int n = 1; n < multiplesOfPrimeFactors.size(); n++) {
          if (isMultipleOfNthPrimeFactor(candidate, n))
            return false;
        }
        return true;
      }
    
      private static boolean
      isMultipleOfNthPrimeFactor(int candidate, int n) {
       return
         candidate == smallestOddNthMultipleNotLessThanCandidate(candidate, n);
      }
    
      private static int
      smallestOddNthMultipleNotLessThanCandidate(int candidate, int n) {
        int multiple = multiplesOfPrimeFactors.get(n);
        while (multiple < candidate)
          multiple += 2 * primes[n];
        multiplesOfPrimeFactors.set(n, multiple);
        return multiple;
      }
    }

    https://habr.com/ru/post/508876/
    Вероятно, хватит рекомендовать «Чистый код»
    > Я остановлюсь на ещё одном вопиющем примере кода. Это генератор простых чисел из главы 8:

    Запостил: gost, 03 Июля 2020

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

    • Какой чистый кот )))
      Ответить
    • А как бы ты написал на шестой джаве н апример?
      Ответить
      • Не называл бы функции так, чтобы их имена приходилось выписывать на отдельной строке.

        Но вообще, я не настоящий ма-те-ма-ти-к и с алгоритмами кобенаций генераций простых чисел знаком слабо. А понимать смысл этой ёбанной портянки я решительно отказываюсь, потому что без подсветки тупо не вижу, какие функции вызываются.
        Ответить
        • Кажется , что тут такая предметная область, что их короче хуй назовешь не проебав читаемость
          Ответить
          • Обычно в этой предметной области переменные называются n, f, i, j и k2. ОП - еретик.

            З.Ы. Причём подразумевается, что ты знаешь что означают p, q и n в конкретной задаче т.к. они взяты из общеизвестных формул. Никаких комментариев об этом не будет.
            Ответить
            • Меня всегда умиляло, что в каждой области математики есть свои p, q и n.
              Они могут иногда по разному писаться, иногда вообще одинаково.
              Ответить
              • Дык понятий много, а букв всего 52 (иногда плюс немного греческих). А учитывая, что большую часть истории ма-те-ма-ти-ки ма-те-ма-ти-ки писали руками на бумаге/пергаменте/etc, традиции называть переменные длинно и понятно как-то не появилось.
                Ответить
                • Ну вообще конечно код не обязан быть понятным для того, кто не умеет в предметную область.

                  Если я не знаю, что такое "ip", то нехуя мне лазить в код для работы с сетью.
                  Если я не знаю, что вероятность это "p", то нехуя мне лазить в код про вероятность.
                  Так что может быть толика логики тут есть.
                  Ответить
                  • Пожалуй, соглашусь, но без фанатизма: делать код доступным только для разумов элиты тоже не стоит.
                    Ответить
                    • int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);

                      Смотри не перепутай.
                      Ответить
                      • Так RSA и сам так описан, с p,q,d итд
                        Ответить
                      • Ну так-то Макака права: в аргументах у функции — конвенционные названия, примерно как «IP» в сетях.
                        А вот «set0» — это да, жопа какая-то непонятная.
                        Ответить
                        • set0, set1, get0 и get1 - это у них конвенция про владение и рефкаунтинг. И без неё раньше было очень, очень, очень хуёво.

                          З.Ы. Кто-то там говорил, что RAII не нужен и программист сам справится?
                          Ответить
                          • показать все, что скрытоvanished
                            Ответить
                          • >З.Ы. Кто-то там говорил, что RAII не нужен и программист сам справится?

                            Ну вроде как ручное кручение счетчика ссылок по явной, простой и хорошо задокументированной это не самая большая проблема.

                            Делать что-то вручную неприятно, но не смертельно. Если конечно ты точно понимаешь, что делать.
                            Ответить
                            • Жопа в том, что раньше этой конвенции не было. И понимать что ты делаешь и что вообще происходит было на порядок сложнее.
                              Ответить
                              • Я как-то ковырялся в коде, где не было четкой политики владения.

                                То-есть каждый раз надо было думать "а кто создал этот объект, а когда мне его удалить, а вдруг не мне, а вдруг он уже удален?".
                                И это самый пиздецкий пиздец и ад
                                Ответить
                                • > самый пиздецкий ад

                                  Не... Есть ещё сишная асинхронщина. Тот самый момент, когда ручное управление ресурсами встречается с тредами и коллбеками.

                                  И никто ведь не опишет, что коллбек тебе могут позвать во время close или даже после него.
                                  Ответить
                            • Делать что-то вручную не смертельно только тогда, когда если ты забудешь что-то сделать — тебя в обязательном порядке отругает конпелятор. Ну, например, когда ты в ЙАЖУ приходишь и целый день пишешь «public void setYetAnotherField(Huj huj); public Huj getYetAnotherField();». Забудешь какой-нибудь очередной «public» — похуй, конпелятор или IDE скажут.

                              Но совсем другое дело — это когда ошибка в тупой и утомительной рутине приводит к утечкам ресурсов, дедлокам и прочим гейзенбагам. Проблема в том, что человек чисто физически не может все 100% времени быть в абсолютно полной концентрации, он в любом случае её теряет и ошибается. Ну а самое неприятное то, что тупая и утомительная рутина катастрофически снижает концентрацию. Поэтому когда тупая и утомительная рутина является крайне важной частью программирования, ошибки в которой приводят к крайне неприятным и трудноотлавливаемым багам… Ну, это хуёво.

                              Ручное управление ресурсами а-ля си лучше «RAII» тогда и только тогда, когда над проектом работают исключительно никогда не ошибающиеся сверхлюди. Ну или когда проект — это маленькая программка на 1000 строк (500 из которых занимают ручные выделения/освобождения ресурсов :-), да.
                              Ответить
                              • А остальные 400 - "обработка" ошибок.
                                Ответить
                                • А если код писал фанатик Дийкстры, то остальные 800.
                                  void *getShit()
                                  {
                                      void *ptr1 = malloc(42);
                                      if (!ptr1) {
                                          return NULL;
                                      }
                                      
                                      void *ptr2 = malloc(43);
                                      if (!ptr2) {
                                          free(ptr1);
                                          return NULL;
                                      }
                                      
                                      void *ptr3 = malloc(43);
                                      if (!ptr3) {
                                          free(ptr1);
                                          free(ptr2);
                                          return NULL;
                                      }
                                      
                                      // Зато без goto!
                                      // ...
                                  }
                                  Ответить
                                  • Блин, я помнится писал код про что-то COM'овское. Сишный пример занимал сотни строк и выглядел весьма серьёзно. Большую часть кода там создавали и освобождали комовские строки и массивы и обрабатывали ошибки от всей этой поебени.

                                    В крестах с готовыми RAII обёртками это уместилось в десяток строк.

                                    В питоньей консольке в одну.
                                    Ответить
                                    • > писал код про что-то COM'овское
                                      Ух, бля. Сочувствую.
                                      [/color]
                                      Ответить
                                    • Поди, табло от кассового аппарата подключал?
                                      Ответить
                                    • Угу, в ком надо AddRef.

                                      Яблы когда вводили свой ARC, они посчитали, что огромная часть типовой программы это retain/release.
                                      Ответить
                                      • > AddRef

                                        Да это хуйня. Ты вот попробуй заполнить безопасный массив из вариантов, в которых лежат строки. Вот где самый ад начинается.
                                        Ответить
                                  • >фанатик Дийкстры, то остальные 800

                                    Дейкстра же основал секту одноразвратников.
                                    Потому нееет, ретурнами тут не обойтись.
                                    Нужно ебошить флажок состояния или делать вложенные ифы.
                                    Ответить
                                    • Ну кстати со вложенными ифами оно не так уж и ужасно будет смотреться. По крайней мере квадратичного роста очисток не будет. Да и нулл в указателе вместо флажка вполне канает.
                                      Ответить
                                      • Зато будет семь уровней вложенности, и программировать ты будешь где-то в районе 80-й колонки
                                        Ответить
                              • Да блин) Я не спорю с тем, что у raii есть плюсы, я в том тредике лишь отметил, что они усложняют систему, и за эти плюсы приходится платить. Бесплатных абстракций не бывает.

                                А тут я сказал, что жить с ручным RC можно, если есть строгие правила когда и что увеличивать.

                                Если правил нет, то все, пиздец, жить нельзя вообще.

                                И разумеется я согласен, что бойлерплецт это плохо. Жаве следует сгореть в аду, например
                                Ответить
                              • > тогда и только тогда, когда над проектом работают исключительно никогда не ошибающиеся сверхлюди
                                Цари
                                ftfy

                                >или когда проект — это маленькая программка на 1000 строк
                                Царская демо программа-выебон на 100 строк чтобы слить лалок в хламину.
                                Ответить
            • Давайте сравним дорожные знаки в разных странах.

              В странах, принявших Венскую конвенцию о дорожном движении, можно увидеть круглый знак с чёрным числом на белом фоне с красной обводкой. Все знают, что это предельно разрешённая скорость в км/ч.

              В США же можно увидеть охрененно длинную прямоугольную табличку (такую, что шею сломаешь, пока её всю разглядишь), на которой написано: «SPEED LIMIT 60 MPH».

              Если бы эти знаки встречались редко, было бы удобно писать, как в США, чтобы всё было разжёвано и чтобы не напрягать память, вспоминая, знак какой формы и какого цвета что означает. Но когда эти знаки через каждые несколько метров, читать длинные надписи тупо некогда. Именно поэтому я за Венскую конвенцию.

              К чему это я? Если у нас большущая функция, её можно назвать длинно. Например, PrimeGenerator. Простительно даже назвать ещё длиннее, чтобы не вспоминать, что она генерирует. Например, PrimeNumbersGenerator. А вот внутри функции имя каждого счётчика делать длинным ни к чему. Хватит и комментария при объявлении переменной.
              Ответить
              • То-есть ты за itoa и hton?
                Ответить
                • Если приведёшь реальный пример формулы, в которой они встречаются десяток раз, то за них.
                  Ответить
                • Я за, это хорошие и запоминающиеся мнемоники. Integer To ASCII, Host To Network — просто и понятно.
                  Ответить
                  • а асембрел тебе нравится с его двух-трех буквенными мнемониками?
                    Ответить
                    • Ну да. Мнемоники на то и мнемоники, что они должны быть максимально короткими и запоминающимися. Просто потому, что в ассемблерном коде их много.
                      Ответить
                      • Ну вот мне кажется, что асемблеру не помешали бы нормальные мнемоники из двух-трех слов. Потому что их овердохуя же, я хз кто вообще может их всех запомнить
                        Ответить
                        • Дык когда на ассемблере реально писали программы, этих мнемоник дай Страйкер сотня была, из которых активно использовался хорошо если десяток.

                          А сейчас на ассемблере пишут разве что с интринсиками (которые как раз подробно развёрнутыми).

                          А у тех, кто занимается реверсом, всегда есть под рукой мануал. В «x64dbg», например, можно через «Ctrl+F1» для любой инструкции вызвать подробную справку, а если нажать «Ctrl+Shift+F1» — напротив инструкций будет их краткое описание: https://i.imgur.com/ZF320si.png. И, честно говоря, правая панель не выглядит особо удобной в чтении.
                          Ответить
                          • > реверсом

                            Лол, да популярных инструкций очень мало, на самом деле. Конпеляторы ещё более консервативны чем люди. Я по-моему за пару дней их все встретил и запомнил.

                            А остальные либо поштучно в лютой системщине, либо кучками в лютом матане, либо вообще устарели и не используются.

                            З.Ы. Даже если конпелятор юзает SSE для "векторизации", то по большей части это xor для зануления да mov.
                            Ответить
                            • Подтверждаю.

                              > А остальные либо поштучно в лютой системщине, либо кучками в лютом матане, либо вообще устарели и не используются.
                              Ну вот, как раз для них и есть «Ctrl+F1». Ну и для SSE/AVX/MMX/3DNow! и прочего дерьма.
                              Ответить
                        • Жопа в том, что в ассемблере даже с короткими мнемониками получается ДОХУЯ текста. И если их делать длиннее - ты через эту стену текста вообще не продерёшься.

                          Разве что всякие SSE можно было бы чуть подробнее расписать. А остальное норм, имхо.
                          Ответить
                          • показать все, что скрытоvanished
                            Ответить
                            • А хер знает, мне для асма подсветки хватает.

                              > внятный хелп

                              Ха-ха. Почитай-ка описание инструкции ret на досуге. Там 10 страниц из которых 8 - псевдокод с алгоритмом его работы.

                              З.Ы. Причём, блин, мне однажды реально пришлось этот псевдокод читать.
                              Ответить
                              • Столько страниц — это на случай перехода между сегментами, работающими в разных режимах (разные кольца защиты, разная дефолтная разрядность адреса и данных и т. п.)?
                                Ответить
                                • Ага. DPL, RPL, CPL, HujPL.
                                  https://c9x.me/x86/html/file_module_x86_id_280.html
                                  Ответить
                                  • Ну, значит, все багры только от RETF, которая прыгает между сегментами. В случае RETN всё проще (там только исключение может вылететь, если адрес разврата нехороший).
                                    Ответить
                                • Забавно, что у iret псевдокод короче. Хотя казалось бы, что он больше работы делает.
                                  Ответить
                                  • Мне так не показалось:
                                    https://c9x.me/x86/html/file_module_x86_id_145.html

                                    Да, отсутствует одна ветка: у IRET нет версии с «ближним развратом», потому что предугадать, какой сегмент будет текущим, когда сработает прерывание, невозможно.
                                    Ответить
                  • vsnwprintf!
                    Ответить
                    • Кстати, вечно блуждаю в этом говне.

                      Когда мне надо вывести широкий чар, мне приходится подглядывать в доку.
                      Ответить
                      • А помните нашу любимую библиотеку «ncurses» с такими же названиями функций? Там буква «w», в зависимости от расположения, может означать либо уникодный символ («wide char»), либо вывод в окошко («window»).

                        Реальный пример:
                        • getstr — ввод «узкого» символа из неограниченной области;
                        • wgetstr — ввод «узкого» сивола из окошка;
                        • get_wstr — ввод «широкого» символа из неограниченной области;
                        • wget_wstr — ввод «широкого» символа из окошка.

                        Попрошу не путать, а то могут и напутать. Скажут, никакой он не «window», а «wide».
                        Ответить
                    • > printf
                      Какое-то форматирование строки со стандартными процентными мудификаторами.

                      > snprintf
                      Форматирование с записью в строку.

                      > snprintf
                      Запись в строку максимум n символов.

                      > wsnprintf
                      Запись wchar_t, широких символов.

                      > v
                      А вот это забыл. Кажется, запись из va_list, то бишь переменных аргументов?..

                      Какой анскилл )))
                      Ответить
                    • Проверил.
                      Наебал ты меня, нет такой функции, только
                      int vwprintf (const wchar_t* format, va_list arg);
                      Print formatted data from variable argument list to stdout
                      Ответить
              • Поддерживаю nemyxa. В попытке понять, какую функцию вызывает «if (isLeastRelevantMultipleOfNextLargerPrim eFactor(candidate))», мне пришлось несколько раз (!) прыгать глазами туда-сюда, сравнивая отдельные части этого шедевра ЙАЖАименования.

                Удивительно, что массив простых чисел у автора назван «primes», а не «arrayOfFirstNaturalNumbersThatIsNotAPro ductOfSmallerNaturalNumbers».
                Ответить
                • А предложи более внятное название функции?
                  Ответить
                  • Предлагаю убрать нахуй это религиозное дерьмо.
                    private static boolean isPrime(int candidate) {
                        int nextLargerPrimeFactor = primes[multiplesOfPrimeFactors.size()];
                        int leastRelevantMultiple = nextLargerPrimeFactor * nextLargerPrimeFactor;
                        
                        // is Least Relevant Multiple Of Next Larger PrimeFactor
                        if (candidate == leastRelevantMultiple) {
                            multiplesOfPrimeFactors.add(candidate);
                            return false;
                        }
                        
                        // is Not Multiple Of Any Previous Prime Factor
                        for (int n = 1; n < multiplesOfPrimeFactors.size(); n++) {
                          if (isMultipleOfNthPrimeFactor(candidate, n))
                            return false;
                        }
                        return true;
                    }


                    Автор как бы намекает нам, что благодаря его охуительному стилю наименования код становится самодокоментируемым™, но это нихуя не так. Понять его можно только убрав эту лапшу из методов и добавив вменяемых комментариев.
                    Ответить
                    • Фаулер еще говорил, что лучше правильно назвать метод или переменную, чем использовать комментарий.

                      У меня нет strong opinion, и твой код кажется мне примерно таким же по читаемости
                      Ответить
                      • > правильно называть метод

                        Ну не до маразма же с методами на 3 строчки, которые по-отдельности один хер понять невозможно.
                        Ответить
                        • А где лимит маразма?

                          Где-то читал, что метод не должен быть длине трех слов (предлоги не считаются)
                          Ответить
                          • > трёх слов

                            Ну это уже форт какой-то.
                            Ответить
                          • > где лимит маразма

                            А х.з., имхо его чувствовать надо. В этом и заключается скилл программиста.

                            Если ты начинаешь мельчить - полезный код тонет в бойлерплейте от описаний функций и их вызовов. Плюс есть риск разбить простой и понятный фрагмент на куски, которые по-отдельности не понять.

                            Если ты пишешь портянку - она не входит в экран и её очень сложно осознать и удержать в памяти. Особенно если там куча переменных и происходит что-то нетривиальное.

                            Надо какой-то середины держаться, чтобы и связанные вещи на куски не порвать (high cohesion) и независимую хуйню в кучу не свалить (low coupling).
                            Ответить
                      • > правильно назвать метод
                        Ну я так-то не спорю, что методы нужно называть понятно. Я против возведения принципа «DRY» в ранг религиозной догмы, как это в ТС-коде сделано. Разбивать методы на огрызки по две строки просто потому, что их можно разбить — это, ИМХО, идиотизм. А уж разбивать методы на огрызки по две строки, которые имеют хуеву тучу побочных эффектов — это вообще пиздец какой-то.
                        Вот, например, «boolean isPrime(int candidate)»: любой вменяемый человек просто по названию и сигнатуре скажет, что это чистая функция. И она даже используется как чистая функция:
                        int primeIndex = 1;
                        for (int candidate = 3;
                                primeIndex < primes.length;
                                candidate += 2) {
                            if (isPrime(candidate))
                                primes[primeIndex++] = candidate;
                        }

                        Но нет, нихуя, функция с префиксом is у нас мало того, что имеет запутанные побочные эффекты, так ещё и не реентерабельна. Охуеть.
                        Ответить
                        • > нереентерабельна

                          Более того, её вообще нельзя звать джважды для одного и того же числа. И вне цикла generate она вообще неюзабельна т.к. она полагается на эффекты от этого цикла.

                          Т.е. это какой-нибудь checkCandidate если уж хочется вынести, но никак не isPrime.
                          Ответить
              • А сколько там в Штатах вообще видов знаков, например?

                Если ты привык видеть SPEED LIMIT, то считываться он будет ничуть не хуже, чем круглый знак с чёрным числом на белом фоне с красной обводкой. Просто потому что опыт и привычка.

                Пиктограммы и хитровыделанные обозначения это хорошо, только вот, если говорить про знаки, я никак не могу увидеть логику в 7.1.1 и 7.2.1. Было бы написано словами, сразу стало бы понятнее.

                С другой стороны, иконки это хорошо в нашем ёбаном европейском Вавилоне - куда не приедешь, а там круглый знак с чёрным числом на белом фоне с красной обводкой.
                Ответить
                • Самый багор — это знаки 3.1 «Въезд запрещён» и 3.2 «Движение запрещено». Между ними есть разница, и заключается она в списке исключений, кому под этот знак проезжать можно. Эту разницу и пиктограммой сложно выразить, и текстовым списком тоже сложно, ибо он будет очень длинным. Хотя если подумать, для чего их ставят, всё становится логичным. 3.1 («Кирпич») обычно ставят там, где одностороннее движение, направленное в лоб смотрящему на этот знак, а 3.2 (обкусанную редиску) — там, где регулярное движение не организовано и на каждом шагу могут поджидать неприятности.
                  Ответить
                  • P.S. 3.1 и 3.2 — это по российским ПДД, конечно. В оригинальной Венской конвенции они обозначались как C1a и C2 соответственно. Почему у номера первого знака суффикс «a»? Потому что допускался вариант «C1b», на котором вместо кирпича была перечёркнутая чёрная стрелка (типа как на знаке «Поворот запрещён», но только прямая).

                    Какой артефакт )))
                    Ответить
                • >> А сколько там в Штатах вообще видов знаков, например?

                  Самый непонятный знак — это «даймонд сайн» — оранжевый квадрат, повёрнутый на угол, внутри которого что-то нарисовано. Жопа в том, что они вообще никак не стандартизированы. Некоторые подобные знаки существуют в единственном экземпляре.

                  Дональд Кнут во время своего путешествия по США и по Канаде собрал коллекцию «бриллиантовой питушни»:
                  https://www-cs-faculty.stanford.edu/~knuth/diamondsigns/diam.html

                  Полный список «diamond signs»:
                  https://www-cs-faculty.stanford.edu/~knuth/diamondsigns/list.html

                  Чуть-чуть Канады:
                  https://www-cs-faculty.stanford.edu/~knuth/diamondsigns/canadian.html

                  Чуть-чуть Австралии и Новой Зеландии:
                  https://www-cs-faculty.stanford.edu/~knuth/diamondsigns/australian.html
                  https://www-cs-faculty.stanford.edu/~knuth/diamondsigns/newzealand.html
                  Ответить
    • while (multiple < candidate)
          multiple += 2 * primes[n];
      Я конечно понимаю, что деление тормозит и его лучше избегать... Но не таким же образом.

      З.Ы. Или там какая-то хитрая магия, что обычно 1-2 итерации?
      Ответить
      • В том-то и дело что код хуёвый.

        Даже понимая предметную область этот ебаный джавизм очень трудно читать.

        УПД: Сейчас в ИДЕ киду, поинлайню методы, посмотрим как он станет НАМНОГО проще.
        Ответить
      • >Или там какая-то хитрая магия, что обычно 1-2 итерации?
        Оно идёт по нечётным.
        3, 9, 15, 21
        5, 15, 25, 35
        7, 21, 35
        А явные составные (чётные) 6, 12, 18 скипает.
        Ответить
    • https://youtu.be/7ilPYMT0Kro
      Ответить
    • Недавно нашёл старую книжку по кодингу. Полистал её.

      Я охуел насколько быдляцкие листинги с кодом там приведены.

      Такое ощущение что их студентота насрала.

      А ведь многие по этим книгам учатся погромировать, ёпт.
      Ответить
    • Заинлайнил всё говно в 2 метода, проверяйте.

      public class PituhGenerator {
          private static int[] primes;
          private static ArrayList<Integer> multiplesOfPrimeFactors;
      
          static int[] generate(int n) {
              primes = new int[n];
              multiplesOfPrimeFactors = new ArrayList<Integer>();
              primes[0] = 2;
              multiplesOfPrimeFactors.add(2);
              int primeIndex = 1;
              for (int candidate = 3;
                   primeIndex < primes.length;
                   candidate += 2) {
                  if (isPrime(candidate))
                      primes[primeIndex++] = candidate;
              }
              return primes;
          }
      
          static boolean isPrime(int candidate) {
              int nextLargerPrimeFactor = primes[multiplesOfPrimeFactors.size()];
              int leastRelevantMultiple = nextLargerPrimeFactor * nextLargerPrimeFactor;
              if (candidate == leastRelevantMultiple) {
                  multiplesOfPrimeFactors.add(candidate);
                  return false;
              }
              for (int n = 1; n < multiplesOfPrimeFactors.size(); n++) {
                  int multiple = multiplesOfPrimeFactors.get(n);
                  while (multiple < candidate)
                      multiple += 2 * primes[n];
                  multiplesOfPrimeFactors.set(n, multiple);
                  if (candidate == multiple)
                      return false;
              }
              return true;
          }
      
      }
      Ответить
      • Эм, они лезут в неинициализированную часть массива primes (ну ок, занулённую раз джава)?

        Для candidate == 3 у нас в обоих массивах лежит только джвойка. И в строке primes[multiplesOfPrimeFactors.size()] мы лезем к элементу за этой двойкой. Странная логика.
        Ответить
        • Решето Эратосфена же.

          Точка входа: generate. Но тем не менее это говно и однопоточная питушня.

          Второй поток с другим n всё распидорасит.
          Ответить
          • Да похуй пока на потоки. Что-то мне намекает, что это код вообще не рабочий. Мы же isPrime(3) зовём прямо в generate. И в массивах лежит только двойка.
            Ответить
            • Он сделает одну итерацию, не сможет поделить 3/2. И выйдет с return true;
              Ответить
              • Блядь.

                primes = {2, 0...}
                multiplesOfPrimeFactors = {2}
                candidate = 3
                nextLargerPrimeFactor = primes[1] = 0 <--- читаем хуйню
                leastRelevantMultiple = 0

                В итоге multiplesOfPrimeFactors.add(candidate) будет вызван только когда кандидат станет равен квадрату нуля. Т.е. никогда.

                Код тупо не рабочий.
                Ответить
                • А иде не криво отрефакторила?

                  Какой образец )))

                  private static boolean isPrime(int candidate) {
                      if (isLeastRelevantMultipleOfNextLargerPrimeFactor(candidate)) {
                        multiplesOfPrimeFactors.add(candidate);
                        return false;
                      }
                      return isNotMultipleOfAnyPreviousPrimeFactor(candidate);
                    }
                  
                    private static boolean
                    isLeastRelevantMultipleOfNextLargerPrimeFactor(int candidate) {
                      int nextLargerPrimeFactor = primes[multiplesOfPrimeFactors.size()];
                      int leastRelevantMultiple = nextLargerPrimeFactor * nextLargerPrimeFactor;
                      return candidate == leastRelevantMultiple;
                    }
                  Ответить
                  • Ну или хабропидоры криво код скопипастили из книги или в самой книге косяк.
                    Ответить
                    • Да судя по коду Макконел или его литературые негры сами запутались в своём говне.
                      Ответить
                      • Кажется что это не Макконел, а Боб Мартин.
                        Ответить
                        • Да я в их сортах не разбираюсь.

                          Читал это всё ещё лет 10 назад, некоторые места и даже главы мне совсем не зашли.

                          Ещё тогда такое чувство было, что там местами хуита написана.
                          Ответить
      • Что сразу бросается в глаза.

        1. Лалка использует массивы, там где их использовать не надо.
        >primes[primeIndex++] = candidate;
        Ручное петушение с primeIndex, когда есть new ArrayList<Integer>(n);

        2. Код принципиально однопоточный
        >private static ArrayList<Integer> multiplesOfPrimeFactors;
        Мало того что стасики говно, так можно аргументом в isPrime передавать.

        Итд.
        Ответить
        • >Ручное петушение с primeIndex, когда есть new ArrayList<Integer>(n);
          Если бы речь шла не про праймы, то я обратил бы твое внимание на количество занимаемой памяти.
          Ответить
          • Я ещё в универе игрался, многократно писал такую хуйню.

            Самое лучшее решето получается при использовании битовых масок (флаг простое или нет).
            Как в класическом алгоритме Эратосфена, идём и зачёркиваем составные.

            >количество занимаемой памяти
            Оно и здесь довольно хуёвое.
            Ответить
        • 3. Для решета Эратосфена мы добавляем все делители
          >multiples.add(2);

          Но т.к. идём по нечётным то потом начинаем счёт с 1.
          >for (int n = 1; n < multiples.size(); n++) {
          Зачем? Зачем?
          Ответить
    • Ещё упростил, заодно сделал код без стейтовых сайд-эффектов.
      ArrayList<Integer> degenerate(int n)
       {
          ArrayList<Integer> multiples = new ArrayList<>(), primes=new ArrayList<>(n);
          primes.add(2);
          multiples.add(2);
          for (int candidate = 3;
               primes.size() < n;
               candidate += 2
          ) {
              if (isPrime(candidate,multiples, primes))
                  primes.add(candidate);
          }
          return primes;
      }
      
      boolean isPrime(int candidate, ArrayList<Integer> multiples, ArrayList<Integer> primes)
      {
          int nextPrime = primes.get(multiples.size());
          if (candidate == nextPrime * nextPrime) {
              multiples.add(candidate);
              return false;
          }
          for (int n = 1; n < multiples.size(); n++) {
              int multiple = multiples.get(n);
              while (multiple < candidate)
                  multiple += 2 * primes.get(n);
              multiples.set(n, multiple);
              if (candidate == multiple)
                  return false;
          }
          return true;
      }
      Ответить
      • Лучше пофикси код чтобы он работал.
        Ответить
        • Мне кстати сразу не понравилось что они с единицы счёт начинают (https://govnokod.ru/26791#comment557210)

          >пофикси код чтобы он работал.
          UPD: https://ideone.com/EpdmTi
          Ответить
          • А как же челлендж про перекладывание двух спичек?)
            Ответить
            • Я добавил -1 в то место и оно заработало.

              https://ideone.com/EpdmTi

              Какой «Чистый код» )))
              Ответить
              • > заработало

                А чойта в multiples только двойка валяется после того как алгоритм завершён? Четвёрка там тоже никогда не выпадет.
                Ответить
                • Стоп. Я убрал -1 и оно нормально работает.

                  https://ideone.com/ODWN2t
                  Ответить
                  • А, понял. Оно для тройки вылетает за границу и сравнивает с нулевой хуетой. Но потом для следующих чисел там в массиве уже есть тройка и всё норм сравнивается. Пора мне спать.

                    Но всё равно какой чистый и понятный код )))
                    Ответить
              • Не могу пока придумать как пофиксить добавление в этот массив. Туда по идее свежие простые числа должны попадать.
                Ответить
                • Так исходный код рабочий.
                  И первая отрефакторенная версия тоже.
                  Я проверил.
                  Ответить
            • Блядь. Я ещё эпичный баг поймал.

              Если System.out.println(generate(10));
              даёт нормальный результат
              [2, 3, 5, 7, 9, 11, 13, 15, 17, 19]

              То System.out.println(generate(50)) высирает степени тройки
              [2, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]
              Ответить
              • > нормальный результат

                9

                Да оно просто все нечётные вываливает потому что в multiples никогда ничего не суётся и тестить числа нечем.
                Ответить
    • наконец-то выдохнул, что и не стоило читать
      Ответить
    • Переписал на си, проверьте:
      #define N 30
       
      int p[N] = {2}, m[N] = {2}, k = 1;
       
      static int isprim(int x) {
          int mk = m[k];
          if (x == mk * mk) {
              m[k++] = x;
              return 0;
          }
       
          for (int i = 1; i < k; ++i) {
              int mi = m[i];
              while (mi < x)
                  mi += 2 * p[i];
              m[i] = mi;
              if (x == mi)
                  return 0;
          }
       
          return 1;
      }
       
      void genprim(void) {
          for (int i = 1, j = 3; i < N; ++i, j += 2)
              if (isprim(j))
                  p[i] = j;
      }

      https://ideone.com/z3WAXz
      Ответить
      • Порефакторил:
        int p[N] = {2}, m[N] = {2}, k = 1;
         
        void genprim(void) {
            for (int i = 1, j = 3; i < N; ++i, j += 2) {
                if (j == m[k] * m[k]) {
                    m[k++] = j;
                    goto np;
                }
         
                for (int i = 1, mi = m[i], pi2 = p[i] * 2; i < k; ++i) {
                    while (mi < j)
                        mi += pi2;
                    if (j == (m[i] = mi))
                        goto np;
                }
         
                p[i] = j;
        np:;
            }
        }
        https://ideone.com/c5pA2k
        Ответить
        • В Си всё просто и понятно.
          Потому я за «Си».

          А вообще я когда-то реализовывал решето без умножений вообще.

          Выделяем bitset интерпретируем его как нечётные.
          0 — 3
          1 — 5
          2 — 7
          3 — 9
          4 — 11
          5 — 13
          6 — 15
          ...

          Сначала он забит нулями. 0 - простое, 1 - составное.

          Проходим с шагом первого простого элемента (3), записываем во все третьи элементы (9, 15 ,21 ...) признак составного. Потом ищем следующее простое, опять проходим с новым шагом.

          Идти нужно до корня из размера bitseta

          После чего функция isPrime(n) сводится к 0==bitset[n/2-1]
          Ответить
          • А я блоками обрабатывал. Типа делаем битсет метров на сто, выкалываем в нём все составные числа и выписываем из него простые. Потом чистим его и начинаем следующую итерацию.
            Ответить
            • А я тоже всякие хаки сочинял. Типа выкалывал не только нечётные, но и делители тройки.

              Тогда нужно было итерироваться только по 2м делителями из 6ти.
              1 mod 6
              5 mod 6

              for (int i = 1, j = 3; i < N; ++i, j += 2)
                      if (isprim(j))
                          p[i] = j;

              Превращалось в
              for (int i = 1, j = 2; i < N; ++i, j += 6){
                      if (isprim(j+1))
                          p[i] = j+1;
                      if (isprim(j+5))
                          p[i] = j+5;
              
              }


              MAKAKA говорила про занимаемую память.
              Так вот самый компактный способ хранить простые числа нет List<Integer> и не int[].

              Самый компактный способ хранить 1/2х байтный дифф. А т.к. дифф всегда чётный, то его ещё можно на 2 поделить.

              Т.к. мы в решете обходим их последовательно, то просто суммируем дифф к счётчику.
              Ответить
          • > просто и понятно

            Ну вот кстати, я смотрю на этот сишный код и он выглядит понятнее, чем исходная джавахуйня с "говорящими" именами.
            Ответить
        • Бля, точно спать пора. Сплошные опечатки в коде. Пофиксил: https://ideone.com/T9iEQ9
          Ответить
          • Спокойной ночи.
            Ответить
            • Доброе утро! Кукареку!

              Оцените энциклопедию целочисленных последовательностей:
              https://oeis.org/A000040
              Ответить
    • Блядь, два опытных программиста два часа разбирали пример на 70 строк, который по идее должен служить образцом читаемости. Какой чистый код )))
      Ответить
      • Так в этой теме все комментарии написали всего два человека?
        Ответить
        • Здесь в любой теме два человека: ты и Страйкер. Все остальные пользователи — либо твои файки, либо файки Страйкера.
          Ответить
      • Т.е. 4 опытных программиста справились бы за час. А 8 - всего за полчаса.
        Ответить
        • А 24 программиста справились бы за 10 минут.
          Ответить
        • > А 8 - всего за полчаса.

          Этим когда-то марили адепты многоядерности.
          В реальности перепитушня на синхронизацию программистов съест весь буст пирфоманса.
          В итоге 8 человек устроят байкшеддинг на целый день.
          Ответить
          • > Этим когда-то марили адепты многоядерности.
            А потом оказалось, что 95% алгоритмов искаропки не многопоточны, и 95% реальных примеров программ жрут одно-два ядра, пока все остальные 265 ядер простаивают.
            Ответить
            • Так это можно видеть на примере человеческого труда.

              Если команда достаточно большая, а таска тривиальная куча времени уйдёт на обсуждение.

              Хорошо паралелятся полтора землекопа, а полтора десятка быдлокодеров асспараллелятся плохо.

              Это отлично описано у Брукса:

              Мифический человеко-месяц.
              Время выполнения проекта не обратно пропорционально числу программистов, по крайней мере по 2 причинам.

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

              Если есть N программистов, то количество пар программистов равно N(N—1)/2, то есть с ростом числа программистов затраты времени на взаимодействие растут квадратично. Поэтому начиная с какого-то N, рост числа программистов замедляет выполнение проекта.

              Если сроки сорваны, наём новых программистов замедляет выполнение проекта и по другой причине: новичкам требуется время на обучение. В книге сформулирован «закон Брукса»: «Если проект не укладывается в сроки, то добавление рабочей силы задержит его ещё больше».


              Фактически закон Амдала ИРЛ.
              Ответить
              • > добавление рабочей силы задержит его ещё больше

                А вот увольнение должно помочь. Оставшиеся получат временный бонус к скиллам и концентрации. Ненадолго правда. И второй раз это уже не работает.
                Ответить
                • Кстати вот читаю и вижу что Брукс изобрёл конь-цеп-цию big.LITTLE задолго до Арма и Штеуда.

                  Ну это когда в ЦПУ ядра негетерогенны. Есть одно большое, быстрое ядро с кучей транзисторов, и рядом несколько маленьких с малым энергопотреблением.

                  Арм давно такое делает. Но Штеуд тоже решил взять на вооружение, и выпустить пятиядерники (intel pentacore).

                  Разумно, если в группе разработчиков есть один «хороший» программист, реализующий самые критические части системы, и несколько других, помогающих ему или реализующих менее критические части. Так делаются хирургические операции. роме того, по мнению Брукса, лучшие программисты работают в 5-10 раз быстрее остальных.
                  Ответить
                • >А вот увольнение должно помочь

                  Отключение ядер тоже часто увеличивает пирформанс.
                  Особенно в многопроцессорных и NUMA системах, где тратится уйма времени на синхронизацию кешей в разных чипах.
                  Все потоки попадают на один процессор, улучшается cache locality.

                  Так что и здесь аналогия полная.
                  Ответить
                  • показать все, что скрытоvanished
                    Ответить
                    • >Брукс же имел ввиду, что работа не всегда параллелится.
                      По-научному этот нехитрый факт называется «Закон Амдала»

                      >удаление НЕНУЖНОЙ многопотчоности иногда увеличивает скорость, бо не тратится время на синхронизацию

                      А я не рассказывал стори, как пару лет назад оптимизировал плюсовый код?

                      Нашёл значит я место, hot spot это были вложенные один в другой циклы в которых программа проводила 40% времени.

                      Программа была однопоточной.
                      А результаты внутреннего циклы никак друг от друга не зависели, и могли вычисляться в произвольном порядке.
                      Вот их я и решил раскидать по потокам.

                      В общем взял я std::launch::async и довольно быстро расспараллелил.
                      Хотя я сам много стебал шарперов с их LINQ AssParallel(), но мне казалось что буст должен быть, ибо вложенные циклы довольно тяжелые.

                      Каков же был багор, когда программа стала работать примерно так же как и однопоточная версия (может даже чуть медленее).

                      Но при этом она жрала примерно 50% на всех 4х ядрах. Ну то есть в джва раза больше ЦПУ, при чуть меньшей скорости!
                      Ответить
                      • показать все, что скрытоvanished
                        Ответить
                        • >а почему так? Они трогали разные места в памяти и засирали общий кеш

                          Ты знал!

                          Я как раз ниже дописал.
                          https://govnokod.ru/26791#comment557404

                          Там и в однопоточной версии, обращения к памяти были довольно хаотичны (хитрая хеш-мапа).

                          Оказалось что если префетчить следующую итерацию, то количество промахов немного падает.
                          Ответить
                          • показать все, что скрытоvanished
                            Ответить
                            • >ну это очевидно: если два питуха на разных ядрах тормозят, значит они воюют за общий ресурс

                              Не всегда.

                              Иногда может быть ещё более банальная ситуация, когда объём работы для потока настолько мал, что не превышает накладных расходов на создание future и переключение контекстов.

                              На что я неоднократно указывал LINQ-питухам. Так и родился мем AssParallel.
                              https://gcode.space/#!/search?q=assparallel
                              Ответить
                              • показать все, что скрытоvanished
                                Ответить
                                • >Зачем вообще LINQ питухи делают ЖопаПараллель не сняв сначала профиль?

                                  Ответ, по-моему, очевиден.
                                  Лалки накупили четырёхядерников.
                                  Но как же их использовать?
                                  А! Так тут же Микрософт сделал специальный метод ЖопаПараллель, который ускоряет все программы в четыре раза!
                                  Как тебе такое, Царь?

                                  Исходный тред:
                                  https://govnokod.ru/9194#comment127669

                                  По итогу треда выяснилось что LINQ замедляет вычисления раз в 20 (!), а ЖопаПараллел возвращает 1.5х пирформанса.
                                  Ответить
                      • Как выяснилось позже бутылочным горлышком был не ЦПУ, а память.

                        Там случалось очень много кеш-промахов.

                        Так вот пару префетчей помогли гораздо больше чем хвалёная многопоточность.
                        Ответить
                        • показать все, что скрытоvanished
                          Ответить
                          • >VTune
                            Но в Линуксе есть perf. Из коробки.

                            EVENTS=cpu-clock,branches,branch-misses,cache-misses,cache-references,cpu-cycles,instructions,stalled-cycles-backend,stalled-cycles-frontend,ref-cycles,alignment-faults,page-faults,uops_issued.stall_cycles,resource _stalls.any,L1-dcache-load-misses,L1-dcache-loads,LLC-load-misses,LLC-loads,LLC-store-misses,LLC-stores,cycle_activity.stalls_l1d_pending ,cycle_activity.cycles_l2_pending,cycle_ activity.cycles_ldm_pending,cycle_activi ty.cycles_no_execute
                            Ответить
                          • perf stat -e $EVENTS ./some_executable

                            Выведет тебе такую статистику:
                            23117977,883474      cpu-clock (msec)          #    2,140 CPUs utilized          
                            10 520 284 633 581      branches                  #  455,069 M/sec                    (36,84%)
                               219 175 895 918      branch-misses             #    2,08% of all branches          (42,11%)
                                81 646 361 084      cache-misses              #    8,138 % of all cache refs      (42,11%)
                             1 003 288 108 369      cache-references          #   43,399 M/sec                    (42,11%)
                            85 220 435 066 295      cpu-cycles                #    3,686 GHz                      (42,11%)
                            169 449 942 755 454      instructions              #    1,99  insn per cycle           (47,37%)
                             6 337 754 954 828      L1-dcache-load-misses     #   12,25% of all L1-dcache hits    (52,63%)
                            51 727 008 210 095      L1-dcache-loads           # 2237,523 M/sec                    (52,63%)
                                70 501 635 881      LLC-load-misses           #   10,93% of all LL-cache hits     (52,63%)
                               645 246 704 173      LLC-loads                 #   27,911 M/sec                    (52,63%)
                                 6 088 332 384      LLC-store-misses          #    0,263 M/sec                    (10,53%)
                                97 110 739 490      LLC-stores                #    4,201 M/sec                    (10,53%)
                             8 010 468 622 228      cycle_activity.stalls_l1d_pending #  346,504 M/sec                    (15,79%)
                            13 608 132 570 493      cycle_activity.cycles_l2_pending #  588,639 M/sec                    (21,05%)
                            82 511 523 080 579      cycle_activity.cycles_ldm_pending # 3569,150 M/sec                    (26,32%)
                            14 709 941 171 714      cycle_activity.cycles_no_execute #  636,299 M/sec                    (31,58%)


                            Ещё есть perf record (записывает в файл такую же статистику, но по каждой функции).
                            time perf record -e cpu-cycles,branch-misses,mem-loads,mem-stores,ref-cycles --call-graph fp -o perf.log ./a.out


                            И perf report (рисует красивое дерево вызовов).
                            Ответить
                            • показать все, что скрытоvanished
                              Ответить
                              • >Использует процессороспецифичную пишутню, чтобы считывать cache miss

                                Да. У каждого процессора есть специальные счётчики. Оно читает оттуда.
                                Оверхед почти нулевой.

                                Полный список можно получить через perf list

                                У амд раньше было совсем мало.

                                Типа stalled-cycles-backend, stalled-cycles-frontend

                                У Штеуда там пара сотень событий со времён Sandy Bridge.

                                Есть ещё software events, которые считает ОС.
                                В принципе вот эти базовые события есть почти на любом x64 железе 10-летней давности.
                                branch-instructions OR branches                    [Hardware event]
                                  branch-misses                                      [Hardware event]
                                  bus-cycles                                         [Hardware event]
                                  cache-misses                                       [Hardware event]
                                  cache-references                                   [Hardware event]
                                  cpu-cycles OR cycles                               [Hardware event]
                                  instructions                                       [Hardware event]
                                  ref-cycles                                         [Hardware event]
                                
                                  alignment-faults                                   [Software event]
                                  bpf-output                                         [Software event]
                                  context-switches OR cs                             [Software event]
                                  cpu-clock                                          [Software event]
                                  cpu-migrations OR migrations                       [Software event]
                                  dummy                                              [Software event]
                                  emulation-faults                                   [Software event]
                                  major-faults                                       [Software event]
                                  minor-faults                                       [Software event]
                                  page-faults OR faults                              [Software event]
                                  task-clock                                         [Software event]
                                Ответить
                                • показать все, что скрытоvanished
                                  Ответить
                                  • >что на твоей рабочей машине это будет летать, а на других сосать.

                                    Я когда оптимизировал тот код. То проверял на амд и штеуде.

                                    Были такие случаи, когда простая перестановка операций в цикле или ручной unrolling давал пирфоманс +1-2% на штеуде, и -1% на амд. Или наоборот.

                                    Ещё у них префетчи как-то по-разному работают. Но я вычислил общий знаменатель, выбрал инструкцию которая помогал и там и там.

                                    Штеуд всегда более агрессивно префетчил. Ему емнип не нравилось когда я в L1 ложил.
                                    Ответить
      • Проблема в том, что реализации ма-те-ма-ти-чес-ких алгоритмов зачастую невозможно понять без знания этоих самых алгоритмов. Хоть ты зарефакторись и обмажь всё говорящими именами. Тут надо или большой подробный коммент перед методом или отсылку к первоисточнику.

        А тут ещё и очень тонкий трюк с чтением незаполненного слота для тройки, из-за которого я подумал, что код вообще не рабочий. Возможно стоило бы тройку сразу засунуть в результат чтобы лишних вопросов не возникало.
        Ответить
        • > Хоть ты зарефакторись и обмажь всё говорящими именами. Тут надо или большой подробный коммент перед методом или отсылку к первоисточнику.
          Подтверждаю. Без краткого описания алгоритма в комментарии все вот эти вот «isLeastRelevantMultipleOfNextLargerPrim eFactor()» ни на гран не понятнее сишного кода с «p q m2 k».
          Ответить
          • Ну да, я их названия понял только когда разобрался в алгоритме.

            Least relevant multiple для простого числа - это его квадрат. Т.е. например первое число, которое имеет смысл тестить на тройку это девять. А на пятёрку - 25. Ибо у меньших чисел будут меньшие делители, которые будут пойманы раньше.
            Ответить
      • А ведь могли просто использовать js
        var primes = require('primes');
        primes(20);
        // => [2, 3, 5, 7, 11, 13, 17, 19];
        Ответить
    • показать все, что скрытоvanished
      Ответить
      • А зачем тут set? Раз уж решил почти все числа хранить, лучше массив булов заюзать имхо. Ну или битсет если он есть в пидоне. Код почти не изменится.

        З.Ы. Вот всяко в каком-нибудь numpy есть готовая функция.
        Ответить
      • > for i in range(2, MAX)
        > and i > prev_candidate

        Зачем? Зачем? Ты же можешь перед главным циклом положить в n единичку а не ноль и тогда можно тупо начать range с prev_candidate + 1, а не пролистывать каждый раз все числа с самого начала.
        Ответить
        • показать все, что скрытоvanished
          Ответить
          • Ну потому что ты самую наивную версию алгоритма реализовал. А там всё-таки более шустрая.
            Ответить
            • показать все, что скрытоvanished
              Ответить
              • Ну потому что как была наивная реализация, так и осталась. Твой код и на сишке и на джаве будет почти одинаково читаться. Ну разве что на сишке чуть-чуть битоёбства вокруг массива будет.

                А в коде из топика другой алгоритм решета, более сложный.
                Ответить
                • показать все, что скрытоvanished
                  Ответить
                  • По идее — книга по читаемому коду оптимизированной версии решета. Подразумевается, что следование правилам из книги поможет сделать даже сложный, ненаивный алгоритм понятным и читаемым (как оказалось — нет, не поможет).
                    Ответить
                    • Кстати, почему-то мне кажется, что наивный вариант с битсетом быстрее работает.
                      Ответить
                    • Итак, ищем десять миллионов простых чисел на сишке.

                      В левом углу ринга Чистый Кот: 10.7 секунд
                      В правом углу ринга Наивная Хуйня: 2.9 секунды
                      // наивная хуйня
                      for (int i = 2; i < N; ++i) {
                          if (!a[i])
                              for (int j = i; j < N; j += i)
                                  a[j] = 1;
                      }
                      Ответить
                      • Какой багрище )))
                        Ответить
                        • Ну к слову у наивной хуйни массив в 2 раза больше - 180 метров против 80 у чистого кота.
                          Ответить
                        • Ну и наивная хуйня с битами: 2.5 секунды. По памяти у неё уже не 180 метров, а всего 25.

                          Ждём пи с цитатой от царя.
                          Ответить
                      • показать все, что скрытоvanished
                        Ответить
                      • Хм, а разве это решето ищет не все простые числа до N, вместо N простых чисел?

                        UPD: чтобы найти десять миллионов простых чисел решетом, надо сделать решето размером 179'424'673 числа.
                        Ответить
                      • >В правом углу ринга Наивная Хуйня: 2.9 секунды

                        I told ya.

                        https://govnokod.ru/26791#comment557212

                        >>Самое лучшее решето получается при использовании битовых масок (флаг простое или нет).
                        >>Как в класическом алгоритме Эратосфена, идём и зачёркиваем составные.
                        Ответить
                    • Но может быть Чистый Кот асимптотически лучше и Наивная Хуйня сольётся как лалка на больших объёмах?

                      Ищем все 32-битные простые числа. Наивная Хуйня утверждает, что их там 203280221 штук.

                      Выпьем чаю, послушаем музыку, прогуляемся на балкон, почитаем комменты на гк, поиграем в osu и подождём ответ Чистого Кота...

                      Наивная Хуйня: 1m40s (4 гига)
                      Наивная Битуйня: 1m00s (полгига)
                      Чистый Кот: 17m45s (1.6 гига)

                      Какое фиаско )))

                      З.Ы. Блядь лол, наивная реализация настолько наивная, что я там поюзал int вместо байта... Т.е. она 16 гигов жрала вместо не 4. С байтом вообще за минуту все числа вываливает, как и битуйня.
                      Ответить
                      • показать все, что скрытоvanished
                        Ответить
                      • Какой багор )))

                        UPD: И это именно тот случай, когда предварительная оптимизация привела к написанию хуйни.
                        Ответить
                        • Ну да, слиться Наивной Хуйне в 5 строчек одновременно по памяти, пирфомансу, асимптотике и читабельности - это надо постараться.
                          Ответить
                          • А хуле.
                            Царь таких лошков раньше пачками сливал.

                            Ошибка №1: анскильная лалка выбрала джаву.
                            Ошибка №2: глупый отброс не осилил битовые маски и классический алгоритм тысячелетней давности.
                            Ошибка №3: отребье написало книгу и начало учить пацанов.


                            > слиться Наивной Хуйне в 5 строчек одновременно по памяти, пирфомансу, асимптотике и читабельности - это надо постараться

                            В оригинале к тому же код небезопасен и немногопоточен из-за статических переменных и публикации мутабельного массива из кишок класса.
                            Ответить
                            • > выбрала джаву

                              Я с сишным портом сравнивал. Так что там всё честно.
                              Ответить
                              • Я понял.
                                Но с джавой он обосрался бы ещё сильнее.
                                А код получился ещё менее читабельный чем аналогичный Сишный (из-за синтаксического мусора protected static, class,)

                                Пикантности обсёру придаёт тот факт что именно в Жабе отсутствуют const array.

                                То есть он публикует мутабельное говно. И учит так делать посонов.
                                Ответить
                                • Жаба бы скорее всего просто наебнулась с out of memory на таком примере. У неё же нету unsigned int'ов, пришлось бы 64-битные числа в массиве хранить.
                                  Ответить
                                  • показать все, что скрытоvanished
                                    Ответить
                                    • > 61 sec i7 3770k

                                      У меня на сишной наивности и i7 8700k получилось 30 секунд. Неплохой пирфоманс у коко.

                                      З.Ы. Правда там 5 секунд из них уходит на высирание всех чисел в файл, если его закомментить - то 25.
                                      Ответить
                                      • показать все, что скрытоvanished
                                        Ответить
                                        • Да, я с твоим ограничением запускал сейчас. 105097565 чисел, последнее из них 2147483647
                                          Ответить
                                        • > все соснули

                                          Ну блоками считай. Я так когда-то делал когда у меня памяти было мало. Хотя это будет уже не так наивно и кратко, конечно.
                                          Ответить
                                          • показать все, что скрытоvanished
                                            Ответить
                                            • >>Реально, проще на няшной написать

                                              Добро пожаловать в Царский клуб.
                                              К вашим услугам простой и понятный язык, беспрецедентный пирформанс, минимум синтаксического мусора.
                                              Ответить
                                          • показать все, что скрытоvanished
                                            Ответить
                                            • Цеплять юнити ради битэррея это примерно как цеплять нумпай ради нан.
                                              Ответить
                                              • показать все, что скрытоvanished
                                                Ответить
                                                • > прибито гвоздями к 32м битам

                                                  Наименьший общий знаменатель же. Код ограничен возможностями самой хуёвой из платформ. Иначе где-то он не сможет запуститься или будет пиздец неэффективным. Хотели конпелять один раз - вот и жрите говно.

                                                  В крестах и сишке ты ведь не от хорошей жизни под каждую платформу заново конпеляешь свой код.
                                                  Ответить
                                                  • показать все, что скрытоvanished
                                                    Ответить
                                                    • > который зависит от платформы

                                                      Ага, и пройти по всем граблям, на которые наступали сишники.

                                                      Всё-таки текущее решение - наименьшее зло. Массивы на 2 гига мало кому нужны. А если нужны - всегда можно разбить их на блоки. Общий объём памяти то не ограничен. Зато в остальных местах всё консистентно и реально не зависит от платформы.

                                                      Шарп же не системный язык, это больше для всякой опердени где не хочется задумываться о низкоуровневых деталях.
                                                      Ответить
                                                      • показать все, что скрытоvanished
                                                        Ответить
                                                      • >А если нужны - всегда можно разбить их на блоки.
                                                        >Общий объём памяти то не ограничен.

                                                        На самом деле это даже хорошо, что язык заставляет программиста использовать странички.
                                                        Ответить
                                                        • показать все, что скрытоvanished
                                                          Ответить
                                                          • Массивы, хрен с ними они же «низкоуровневые», «царские».

                                                            Другое дело что размеры коллекций прибиты гвоздями к 32-битам.

                                                            https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.count?view=netcore-3.1

                                                            А в жабе к int size(), дописали унизительный коммент, в стиле (вы конечно можете засунуть и больше элементов, но size вернёт вам хуйню).

                                                            >Есть мнение, что страничнки должен использовать менеджер виртуальной памяти, на худой конец фреймворк

                                                            Массив это сполшной кусок памяти.
                                                            С этим большие проблемы.
                                                            А вот List это абстракция. Но жавашки и шарпушки превратили её в абасракцию.
                                                            Ответить
                                                            • > но size вернет вам хуйню

                                                              Какой UB )))
                                                              Ответить
                                                              • >Какой UB )))

                                                                Там не UB, а скорее Math.min(my_real_collection_size, Integer.MAX_VALUE)

                                                                https://docs.oracle.com/javase/7/docs/api/java/util/Collection.html#size()

                                                                int size()
                                                                
                                                                Returns the number of elements in this collection.
                                                                If this collection contains more than Integer.MAX_VALUE elements, returns Integer.MAX_VALUE.
                                                                Ответить
                                                                • Блядь, как меня бесят подобные нарушения инвариантов…
                                                                  Ответить
                                                                  • Ага. Ждём когда big data станет реально большой и они запилят в Жабу long size64() или что-то в этом духе.

                                                                    Но самые отборные лулзы начнутся при вызове:
                                                                    <T> T[] toArray(T[] a)
                                                                    
                                                                    Returns an array containing all of the elements in this collection; the runtime type of the returned array is that of the specified array. If the collection fits in the specified array, it is returned therein. Otherwise, a new array is allocated with the runtime type of the specified array and the size of this collection.
                                                                    
                                                                    If this collection fits in the specified array with room to spare (i.e., the array has more elements than this collection), the element in the array immediately following the end of the collection is set to null. (This is useful in determining the length of this collection only if the caller knows that this collection does not contain any null elements.)
                                                                    
                                                                    If this collection makes any guarantees as to what order its elements are returned by its iterator, this method must return the elements in the same order.

                                                                    Не помню что там с реализациями этого метоад, но по-моему они используют size() для аллокации массива нужного размера.
                                                                    Ответить
                                                                    • > the element in the array immediately following the end of the collection is set to null.
                                                                      Штоблядь?..
                                                                      …Пиздец, тупо взяли и напрямую спиздили из сишки null-terminated массив. Действительно, нахуя напрягаться и придумывать нормальные, вписывающиеся в архитектуру разрабатываемого языка, интерфейсы, когда можно отключить мозг, спиздить что-то из сишки и потечь?
                                                                      Ответить
                                                                      • > This is useful in determining the length of this collection only if the caller knows that this collection does not contain any null elements.

                                                                        Да, очень ржачное применение.
                                                                        Ответить
                                                                        • Да охуеть вообще. Что это вообще за тупая хуйня — одновременно и возврат значения, и выходной параметр? Почему бы, блядь, не сделать «T[] toArray()» и «int toArrayInplace(T[] a)»!?
                                                                          Ответить
                                                                          • >Почему бы, блядь, не сделать «T[] toArray()»

                                                                            Он есть, но им лучше не пользоваться. Ибо он очень хуёвый из-за type erasure.
                                                                            Точнее есть Object[] toArray(), а чтобы было T нужно передать что-то параметром: Class<T>, T или T[], чтобы оно в рантайме могло взять тип.

                                                                            Но прикол даже не в этом. А в том что если даже возвращённый Object[] содержит в себе одни лишь только T (что логично, ибо в коллекции других нету) его невозможно превратить в T[] без ПОЛНОГО копирования и malloca ещё одного массива.

                                                                            И привести этот Object[] обратно в Т[] невозможно никак.
                                                                            Нет никаких кастов способных это осуществить, как в Сишке или Крестах.
                                                                            Ответить
                                                                        • показать все, что скрытоvanished
                                                                          Ответить
                                                                • >> If this collection contains more than Integer.MAX_VALUE elements, returns Integer.MAX_VALUE.

                                                                  Напоминает жёсткие диски стандарта LBA48, которые при запросе размера по протоколу LBA28 возвращают (2^28-1) секторов (≈ 120 гигабайт) вместо реального размера. Правда, у них есть альтернативная команда, возвращающая полный размер софту, поддерживающему LBA48, а вот в «Йаже», похоже, такого альтернативного метода нет.
                                                                  Ответить
                                                                  • Да. Вот я и говорю им ещё предстоит запилить:

                                                                    int size()
                                                                    long mysqlreal_collection_size()
                                                                    Ответить
                                                                    • показать все, что скрытоvanished
                                                                      Ответить
                                                                      • Справедливости ради, к тому времени, когда на эту новую граблю наступят, о ЙАЖЕ будут вспоминать разве что в исторических хрониках.
                                                                        Ответить
                                                                        • показать все, что скрытоvanished
                                                                          Ответить
                                                                          • >сколько RAM будет через 15 лет?
                                                                            Выйдут планки по 2**64 байт?
                                                                            Ответить
                                                                            • показать все, что скрытоvanished
                                                                              Ответить
                                                                              • >Ты в 2005-м году предвидел вот такую планку?

                                                                                У меня в 2005 была планка 512 Мб.

                                                                                К 2025 году, было вполне вероятно увеличение размера обычной планки до 512Гб. 1024 раза за 20 лет.

                                                                                Методика расчёта здесь:
                                                                                https://govnokod.ru/26791#comment557605
                                                                                Ответить
                                                                                • показать все, что скрытоvanished
                                                                                  Ответить
                                                                                  • >не понимаю, почему скорость именно такая

                                                                                    https://en.wikipedia.org/wiki/Moore%27s_law
                                                                                    Ответить
                                                                                    • показать все, что скрытоvanished
                                                                                      Ответить
                                                                                      • > is dead
                                                                                        Да, dead, потому что мы упёрлись в физические ограничения и поддерживать x2 рост уже не можем.
                                                                                        Ответить
                                                                                        • Не совсем.
                                                                                          Ещё лет 10 обещают протянуть, но с меньшими темпами (удвоение плотности в 3-4 года).

                                                                                          Но сам факт что производителей транзисторов из нескольких десятков в 90х, осталось только 2 (TSMC, Samsung) говорит что там всё очень туго.

                                                                                          IBM с AMD отошли в сторону. Да и Штеуд же не от хорошей жизни шестой год стагнирует на 14нм.

                                                                                          Но я же сразу сказал что беру самый оптимистичный из возможных сценарией роста:
                                                                                          >Даже при такой оптимистичной экспоненте
                                                                                          Ответить
                                                                                        • показать все, что скрытоvanished
                                                                                          Ответить
                                                                                          • >тогда зачем приводить его в пример?)

                                                                                            Потому что остальные сценарии роста в перспективе ещё хуже.

                                                                                            Вероятнее всего что в лимит 2**63 байт мы не упрёмся даже через 60 лет.
                                                                                            Ответить
                                                                                          • Затем, что это верхняя граница.

                                                                                            Закон Мура помирает потому, что мы упёрлись в физические ограничения. Продолжать Муровский рост можно только уменьшая размер транзистора — а это бесконечно делать нельзя. На единицах нанометров (именно там, где мы сейчас и находимся) в дело вступает, ехидно потирая лапки, квантушня, и радостно начинает туннелировать электроны — вплоть до того, что вместо сигнала получается белый шум.

                                                                                            А из принципиально нового у нас есть только та же самая квантушня, но, как я писал выше, программировать на ЙАЖЕ под неё не будут.
                                                                                            Ответить
                                                                                  • В 1999-м в организациях на полном серьёзе эксплуатировались 386 с четырьмя мегабайтами оперативки, хотя уже был изобретён «Pentium II».

                                                                                    Тогда был кошмар и ужас с зоопарком техники несопоставимых классов.
                                                                                    Ответить
                                                                          • Неважно. 2^64 байт в обозримом будущем не будет — просто потому, что у классической памяти есть фундаментальные ограничения на плотность записи, а неклассическая — это квантушня, под которую на ЙАЖЕ ничего написать не получится.
                                                                            Ответить
                                                                      • >вместо завоза size_t

                                                                        Нахуй size_t? Что такое size_t? Зачем он для коллекций?
                                                                        Это же блять ЙАЖА, зачем мне знать какого размера size_t на конкретной платформе?

                                                                        Если уж обмазываться абасракциями и жООП лучше интерфейс Number c возможностью вернуть любое число (Int, Long, BigInteger).

                                                                        >чуть дальше
                                                                        2**63 — это очень дохуя между прочим.
                                                                        Да жаба с 4х гиговой коллекцией в куче будет тупить не по-детски. Куча будет гига 32 (Объект минимум 8 байт*4 миллиарда), а задержки гц от stop-the-world секунд по 20.
                                                                        Ответить
                                                                        • показать все, что скрытоvanished
                                                                          Ответить
                                                                          • Пусть размер планки удваивается каждые джва года.
                                                                            Сейчас планка 16 ГБ.

                                                                            Даже при такой оптимистичной экспоненте через 20 лет, среднестатистическая планка будет в 2**10 (1024) раз больше.

                                                                            То есть всего 16ТБ. Это где-то 2**44. До 2**63 закону Мура нужно ещё лет 60 .
                                                                            Ответить
                                                                        • > зачем мне знать какого размера size_t на конкретной платформе?

                                                                          ))))))))
                                                                          Напитон, пидар!
                                                                          Программируешь на сишке - будь добр помнить что какого размера на какой платформе.
                                                                          Ответить
                                                                  • показать все, что скрытоvanished
                                                                    Ответить
                                                                    • Не напоминай. Нарвался я как-то в начале нулевых на динозавра из прошлого века, у которого в BIOS не было «автодетекта» хардов. Если батарейка сядет, «C-H-S» приходилось вбивать вручную (открыв корпус и прочитав на этикетке винчестера либо подобрав), иначе система не загрузится.
                                                                      Ответить
                                                            • показать все, что скрытоvanished
                                                              Ответить
                            • показать все, что скрытоvanished
                              Ответить
              • Смотрите, что нашёл:
                http://pecl.php.net/package/Bitset

                BITSET
                Released under the PHP License 3.01
                
                The BitSet library assists by providing a mechanism to manage sets of bits. This 
                provides a similar API (object-based) to java.util.BitSet with some PHP-specific 
                flavoring.


                Именно поэтому я за «PHP».
                Ответить
                • показать все, что скрытоvanished
                  Ответить
                  • Файл «TODO» состоит из одного слова: «documentation». Нужно залезть в исходники этого расширения и поржать.
                    Ответить
                  • А вообще они даже тесты приложили:

                    <?php 
                    error_reporting(E_ALL ^ E_DEPRECATED);
                     $bitset = bitset_empty();
                    
                     bitset_incl( $bitset, 3 );
                     if( bitset_to_string( $bitset ) == "00010000" )
                          echo "include to empty bitset - ok\n";
                    
                     bitset_incl( $bitset, 1 );
                     if( bitset_to_string( $bitset ) == "01010000" )
                          echo "include to existing part of a bitset - ok\n";
                    
                     bitset_incl( $bitset, 35 );
                     if( bitset_to_string( $bitset ) == "0101000000000000000000000000000000010000" )
                          echo "include after boundary - ok\n";
                    
                     bitset_incl( $bitset, 47 );
                     if( bitset_equal( $bitset, bitset_from_string( "010100000000000000000000000000000001000000000001") ) )
                          echo "include after boundary aligned 1 - ok\n";
                    
                     bitset_incl( $bitset, 48 );
                     if( bitset_equal( $bitset, bitset_from_string( "0101000000000000000000000000000000010000000000011") ) )
                          echo "include after boundary aligned 2 - ok\n";
                    ?>


                    <?php 
                    error_reporting(E_ALL ^ E_DEPRECATED);
                     $bitset = bitset_empty();
                    
                     bitset_excl( $bitset, 2 );
                     if( bitset_to_string( $bitset ) == "" )
                          echo "exclude from empty bitset - ok\n";
                    
                     bitset_incl( $bitset, 1 );
                     bitset_incl( $bitset, 5 );
                     bitset_excl( $bitset, 1 );
                     if( bitset_to_string( $bitset ) == "00000100" )
                          echo "exclude from an existing part of a bitset - ok\n";
                    
                     bitset_excl( $bitset, 33 );
                     if( bitset_to_string( $bitset ) == "00000100" )
                          echo "exclude after boundary - ok\n";
                    ?>


                    <?php
                    $b = new BitSet(); // 64 bits is fine
                    $c = new BitSet();
                    $b->set(2);
                    $b->set(6);
                    $c->set(2);
                    $b->andNotOp($c);
                    var_dump($b->__toString());
                    ?>
                    Ответить
                • > PHP-specific flavoring

                  API с запашком говна?
                  Ответить
    • показать все, что скрытоvanished
      Ответить

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