1. PHP / Говнокод #27506

    +3

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    $a != abs($a)
    $a+abs($a) == 0
    $a && !($a + abs($a))
    $n>>1 > $n
    substr_count($a,"-")
    is_nan(sqrt($number))
    is_nan(log($n))
    !array_shift(explode("-", $num))
    (int)$var === ~~(int)$var
    strlen(strval($num)) != strlen(strval(abs($num)))
    strlen(decbin($n)) == 32
    is_int(strpos(get_headers("http://habrahabr.ru/blogs/php/page$num/")[0], '404'));
    
    function lessThanZero ($num) {
        while (1) {
            if ($num++ == 0) {
                return true;
            }
        }
    }
    
    function is_value_between($value, $begin, $end) {
        return in_array($value, range($begin,$end));
    }

    "Как проверять отрицательное ли число ?
    В мануале в математических функциях не нашёл ."

    https://php.ru/forum/threads/kak-proverjat-otricatelnoe-li-chislo.8208/

    Запостил: kezzyhko, 09 Июля 2021

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

    • lessThanZero понравилась. Особенно условие завершения.
      Ответить
      • > Особенно условие завершения.

        gcc на них нет:
        lessThanZero:
            mov eax, 1
            ret
        Ответить
        • gcc считает зацикливание UB? Или ему возможное переполнение не нравится?
          Ответить
          • И то и другое.

            Оно вернёт true или переполнит int.

            Оно вернёт true или повиснет нахуй.

            Т.е. даже с unsigned это тупо return true. И даже если в цикле не инкрементить, то один фиг return true.

            З.Ы. Нефиг писать функции, которые возвращают только одно значение )))
            Ответить
          • И зацикливание и переполнение знакового — UB. Так как компилятор по умолчанию считает программиста компетентным, то компилятор рассматривает случае, когда UB не возникает. В данном случае вариант один — если num уже 0.

            Если бы num было беззнаковым, тогда всё просто — в конце концов num переполнится и станет равным 0.

            Если бы знаковое переполнение не было бы UB — то же самое.
            Ответить
            • > в конце концов num переполнится

              Убери инкремент и он всё равно выкинет... Либо num уже ноль и мы вернём true либо всё повиснет и нам пофиг, можно тоже вернуть true.
              Ответить
            • > компилятор рассматривает случае, когда UB не возникает

              Программа B называется аппроксимацией программы A, если для всех случаев, в которых A завершается B завершается с тем же результатом.
              Ответить
              • Если в программе А в каких-то случаях возникает UB, то любое поведение программы B в этих случаях будет корректным, поэтому эти случаи можно не рассматривать. Кстати, где-то был говнокод, где в цикле обходился массив, и выходило, что возвращается либо 4 (вроде), либо что-то другое, но после выхода за границы массива. Компилятор оптимизировал это в return 4; — единственный не-UB результат.
                Ответить
                • Не совсем, поведение UB'ов не описано в сёмантике языка. Вообще. Т.е. формальный интерпретатор не сможет перейти в следующий стейт и никогда не сможет доползти до завершающего.

                  Т.е. формально любой UB эквивалентен зависанию.

                  Именно поэтому мы можем аппроксимировать программу с UB'ом при помощи более простой программы, которая забивает на поведение под UB'ом.

                  > за границы массива

                  Это я вроде постила.
                  Ответить
    • Первые два способа неэквивалентны. Или "PHP" и здесь чудит?
      Ответить
    • > В мануале в математических функциях не нашёл .

      Может еще нужно чтоб была особая функция для проверки равенства нулю?
      Ответить
    • В жопоскрипте кстати такая хрень есть
      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign

      The Math.sign() function returns either a positive or negative +/- 1, indicating the sign of a number passed into the argument. If the number passed into Math.sign() is 0, it will return a +/- 0. Note that if the number is positive, an explicit (+) will not be returned.
      Ответить
      • В «PHP» есть gmp_sign для чисел повышенной разрядности.
        Ответить
        • В Python нят никаких gmp_sign. Имення поэтому я за Python.
          Ответить
          • В «Питоне» такие числа из коробки.
            Ответить
            • Правильня.
              Ответить
              • Почему бигинты из коробки есть, а arbitrary-precision floating point arithmetic нет?
                Ответить
                • Как нят, когда есть?
                  >>> import decimal
                  >>> decimal.getcontext().prec = 1000
                  >>> decimal.Decimal(2).sqrt()
                  Decimal('1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641572735013846230912297024924836055850737212644121497099935831413222665927505592755799950501152782060571470109559971605970274534596862014728517418640889198609552329230484308714321450839762603627995251407989687253396546331808829640620615258352395054745750287759961729835575220337531857011354374603408498847160386899970699004815030544027790316454247823068492936918621580578463111596668713013015618568987237235288509264861249497715421833420428568606014682472077143585487415565706967765372022648544701585880162075847492265722600208558446652145839889394437092659180031138824646815708263010059485870400318648034219489727829064104507263688131373985525611732204024509122770022694112757362728049573810896750401836986836845072579936472906076299694138047565482372899718032680247442062926912485905218100445984215059112024944134172853147810580360337107730918286931471017111168391658172688941975871658215212822951848847')
                  Ответить
                  • Нечестно! У тебя длинная константа записана строкой.

                    На уровне языка можно так записать?
                    Ответить
                    • У меня длинная константа записана результатом вычисления корня с произвольной точностью — в данном случае с точностью до одной тысячи десятичных зняков после запятой.

                      Модуль decimal является частью стандартной библиотеки языка.
                      Ответить
                      • Я и в «PHP» так могу:
                        <?php
                        bcscale(1000);
                        echo bcsqrt(2);


                        «bcmath» в поставку входит, но в «Ideone» его почему-то не включили.
                        Ответить
                        • P.S. В пэхапэшном модуле «bcmath» неудобно сделали, что точность задаётся глобально. А в «Питоне» можно создать несколько контекстов с разной точностью?
                          Ответить
                          • Так это и в изначальном bc вроде так.
                            Ответить
                          • > в питоне

                            Ну да, можешь локальный контекст открыть и посчитать что-то, если глобальный крутить не хочется.
                            Ответить
      • Т.е. если я сравню потом его с нулём, у меня получится false т.к. -0 < 0? А нет, нули всё-таки равны.
        Ответить
        • В JS числовой тип запутанный. Хотя носителем является double, всё сделано так, чтобы он был неотличим от целого, если близок к целому. Поэтому и ноль один.
          Ответить
        • <?php
          
          printf("%d\n", "0" == "-0"); // 1
          printf("%d\n", "0" == "0"); // 1
          printf("%d\n", "0" === "-0"); // 0
          printf("%d\n", "0" === "0"); // 1
          
          ?>

          В каком еще языке есть такая хер-ня?
          Ответить
          • В том, в котором есть оператор ===
            Ответить
            • P.S. Мне однажды приснился ЯП с оператором ====
              Ответить
              • Coq?

                Там хоть оператор st =[ cmd ]=> st' можно объявить.
                Ответить
                • В Haskell тоже всякую свою инфиксную хрень можно объявить (а в крестоговне нельзя)
                  https://riptutorial.com/haskell/example/23080/custom-operators
                  Ответить
                  • В крестоговне даже нельзя вернуть ленивость для перегруженных && и ||.
                    Ответить
                  • А можно постфиксную хрень объявить? Вот в «Nim» нельзя, но есть костыль: можно делать так:

                    pethu.<=?=>

                    <=?=> – это типа постфиксный оператор.
                    Ответить
                    • В хаскеле нет, по крайней мере без расширений языка. В coq можно.
                      Ответить
            • А много ли таких языков? В JS например такая херня тоже есть. А где еще?
              Ответить
              • PHP?
                Ответить
              • Я только два знаю.

                === есть в Яибу, но там он означает совсем другое. Кто, не подглядывая в справку, вспомнит его значение?
                Ответить
                • "===" в яибе имеет миллион смыслов. И проверка на range (как in) и на регулярку (как =~) и вроде на принадлежность классу

                  Это просто перегруженный у разных говнов оператор, и он не коммутативен
                  Ответить
                  • Ну вот, а говорили, что у «Руби» максимально ожидаемое поведение.
                    Ответить
                    • А что не так? Я ожидал, что «Руби» говно, так и получается.
                      Ответить
                    • максимально ожидаемое для рубиста

                      хотя мне этот оператор тоже не нравица
                      Ответить
                      • > максимально ожидаемое для рубиста

                        Т.е. в с++ всё тоже норм т.к. "максимально ожидаемо для полностью изучившего стандарт"?
                        Ответить
                        • > максимально ожидаемо для полностью изучившего стандарт

                          То есть, никем не ожидаемое?
                          Ответить
                        • В С++ очень много костыликов ради совместимости, руби в этом плане чуть проще ,конечно
                          Ответить
                  • И вроде там слева нужно ставить известное значение (чтобы интерпретатор выбрал нужную перегрузку), а справа — проверяемое, поэтому получается йода-стайл.
                    Ответить
                    • именно
                      #
                      irb(main):004:0* "A" === String
                      => false
                      irb(main):005:0> String === "A"
                      => true

                      потому я за "яuбy"
                      Ответить
            • Кстати, даже в JS такой херни нет
              importPackage(java.io);
              importPackage(java.lang);
              
              System.out.println("0" == "-0"); // false
              System.out.println("0" == "0");  // true
              System.out.println("0" === "-0"); // false
              System.out.println("0" === "0"); // true

              https://ideone.com/Wsigk8

              PHP зачем-то при "0" == "-0" и "0" == "0" кастует эти "0" "-0" в числа и потом сравнивает, а при === сравнивает их как строки. Нахуя так надо делать?
              Ответить
              • > PHP зачем-то при "0" == "-0" и "0" == "0" кастует эти "0" "-0" в числа и потом сравнивает, а при === сравнивает их как строки.
                Так это давняя смешнявка. Пых (справедливо) считает, что по умочанию ня нём программирует ротоняк, который про эти ваши "типы" ня задумывается, поэтому оператор "==" пытается аргументы-строки привести к числам. В каком-то, кажется, пятом пыхе вообще была встроенная уязвимость, благодаря которой все строки, нячинающиеся с "0e", считались равными. Представь, как это отразилось ня коде пыхомакак, которые сравнивали хэши паролей пользователей через PHP.
                Ответить
                • Кто такой «ротоняк»?
                  Ответить
                • А, так в нём до сих пор эта забава имеется:
                  <?php
                  var_dump("0e123" == "0e51217526859264863");  // bool(true)

                  https://ideone.com/QUmt2m
                  Ответить
                • В каком-то из популярных движков форумов была такая уязвимость. Можно было даже зайти от имени админа, если у него хэш пароля начинался с 0e.
                  Ответить
          • Где тут херня? В первых двух случаях происходит преобразование в числовой тип, поэтому они равны, в третьем сравниваются *строки*, они разные, а в четвёртом, также строки, но они одинаковы.
            Ответить
            • В голове у того, кто придумал эту механику сравнений...

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

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

                  "php" == 0
                  Ответить
                  • Ха!

                    https://wiki.php.net/rfc/string_to_number_comparison

                    В восьмой версии изменили поведение.
                    Ответить
                    • Кокококой кокококошмар!

                      Именно поэтому я не люблю полагаться на неявное приведение, а предпочитаю использовать === и явный вызов strval, intval, floatval etc.
                      Ответить
                      • >Именно поэтому я не люблю полагаться на неявное приведение, а предпочитаю использовать ===

                        Согласен, это предпочтительнее.

                        >явный вызов strval, intval, floatval etc

                        А тут я больше привык к (string) и тд. Смысл не меняется.
                        Ответить
    • как насчет такого метода. "a != sqrt(a * a)"
      Ответить
      • При возведении большого положительного флоата в квадрат, может получиться inf, а извлечение квадратного корня из inf дает inf. К тому же возможны всякие ошибки округления и тогда равенства не будет и при положительных без всяких inf. К тому же если это не флоаты а инты конечной разрядности, возможно переполнение.
        Ответить

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