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

    +14

    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
    [code=cpp]
    #include <iostream>
    #include <cmath>
    
    void foo(double x, double y)
    {
        if (std::cos(x) != std::cos(y)) 
            std::cout << "Я знаю точно невозможное возможно";
    }
    
    int main()
    {
        foo(1.0, 1.0);
        return 0;
    }
    [/code]

    floatы и нуб.

    Запостил: igumnovf, 16 Ноября 2012

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

    • >[code=cpp]
      govnokod.ru и нуб.
      Ответить
    • http://ideone.com/0mEBvi
      Ты думал для нас Америку открыть?
      Тут язык не причем. Это проблема более капитальная на уровне чисел с плавающей точкой и в общем случае не разрешимая.
      Ответить
    • @LispGovno
      Первый блин комом.
      Ответить
    • Разобрался с причиной бага. Внимательно смотрим на дизасм:
      .LFB1011:
              pushl   %ebp
              movl    %esp, %ebp
              subl    $16, %esp
              movl    12(%ebp), %eax
              pushl   %eax
              movl    8(%ebp), %eax
              pushl   %eax
              call    cos
              popl    %ecx
              popl    %eax
              fstpl   -8(%ebp) ; Значение первого косинуса сохранили в переменную
              movl    20(%ebp), %edx
              pushl   %edx
              movl    16(%ebp), %eax
              pushl   %eax
              call    cos ; А второй косинус дошел до сравнения голым
              addl    $16, %esp
              fldl    -8(%ebp)
              fucompp
              fnstsw  %ax
              andb    $69, %ah
              cmpb    $64, %ah
              jne     .L10
              leave
              ret
      Видим, что результат первого косинуса поместили во временную 64-битную переменную, а второй дошел до сравнения без модификаций. По дефолту FPU считает с точностью 80 бит. Из-за этого округления 80->64 один из косинусов стал менее точным.
      Ответить
      • http://ideone.com/be3490
        А жаль...
        Ответить
        • http://ideone.com/xCL6q7
          Такие дела...
          Ответить
          • Так фиксили баг в пыхе, в результате которого он вис на парсинге специально сформированного числа.

            Пых смотрел, изменилось ли число, и прибавлял к нему маленькую дельту. Но вот незадача. Дельту он прибавлял, число подрезалось до 64битного, и совсем не менялось. Но сравнение шло 80битным, поэтому пыхе казалось, что число изменилось, и он занимался этим вечно...
            Ответить
        • У gcc есть опция -ffloat-store, с которой компилятор будет по-честному подрезать 80 битные числа до 64 или 32, в зависимости от нужного типа.
          Ответить
        • А здесь в чём засада?
          Ответить
          • Компилятор оптимизнул код, убрав лишие переменные. volatile в следующем примере форсит сохранение значений в память, а значит, и обрезание разрядов у обоих значений.
            Ответить
      • > pushl
        > movl
        > fstpl

        Это щито за команды такие?
        Ответить
        • Это не Земля и не Африка, родной. Ассемблер Америкэн Телефон энд Телеграф, 215 в тентуре, галактика Кин-Дза-Дза в спирали.
          Ответить
        • l, s и прочие в конце команды показывают размерность операндов. Заметь, что у них еще и аргументы кверх ногами и процентики около регистров. Это в GNU Assembler такой синтаксис применяется на всех платформах, а спизжен он у ассемблера AT&T.

          P.S. gcc с опцией -S выдает код именно в таком формате, а преобразовывать его в интеловский мне влом.
          Ответить
        • Это гццблядство.
          Это ещё ладно, тут всё понятно, а вот синтаксис гццшной асмовставки я там и не осилил, хотя чувствую, что задумка очень хорошая.
          Ответить
          • Ну там заковыки с синтаксисом начинаются на работе с входными, выходными и затененными регистрами. Зато вставка (у опытного программиста) отлично интегрируется с остальным кодом, а не болтается инородным телом мешающим оптимизации, как в некоторых компиляторах.
            Ответить
      • В «Турбопаскале» я всё вычислял только в типе Extended (80-битном). Не было у меня нужды экономить память даже в ДОСе. И видимо, не зря я его выбирал...

        P.S. Сишный аналог, кстати, long double. Но он в разных реализациях компилятора разный. Он не обязан быть 80-битным.
        Ответить
    • http://ideone.com/x1jfuZ
      Ответить
      • Сори, промазал с оценкой.
        Ответить
      • http://ideone.com/7Hyqpt
        Ответить
        • Значит, в сишках не всякий косинус полезен!
          Ответить
        • - #include <cmath>
          + #include <math.h>

          Вот это реально сильное колдунство.
          Ответить
          • этож тоже самое

            какой багор ))
            Ответить
            • Нет. "cmath" - это типа для крестовиков и нужно писать std::, "math.h" - для сишников. К примеру, "ISO" выебнется и будет cmath использовать.
              Ответить
              • Разве <cнечто> в С++ это не тоже самое, что <нечто.h> в няшной (ну с поправкой на std)?
                Ответить
                • Я тоже так думаю. Но лучше спросить у "ISO".
                  Ответить
                • Ну вот тут оказалось, что ещё с поправкой на перегрузку. Гэцэцэшных генериков для сишки не было, когда придумывали <math.h>
                  Ответить
                • По Стандарту говно (за исключением макросов, конечно) из <csth> обязано высираться в неймспейс std::, а в глобальный неймспейс — не обязано (на усмотрение компилятора); из <sth.h> — наборот: в глобальный неймспейс обязано, в std:: — как компилятор решит.
                  Ответить
                  • ну окей, это понятно (ради совместимсти с j123, у которого в контроллерах никаких неймспейсов нет)

                    но я бы ожидал в остальном одинаковово поведения
                    Ответить
                    • Оно там для большинства функций и есть одинаковое. Просто в некоторых местах приходится патчить для лучшей совместимости с крестушнёй, например:
                      The contents and meaning of the header <cstddef> are
                      the same as the C standard library header <stddef.h>,
                      except that it does not declare the type wchar_­t, that
                      it also declares the type byte and its associated operations
                      ([support.types.byteops]), and as noted in [support.types.nullptr]
                      and [support.types.layout].

                      n4659 / [cstddef.syn]
                      Ответить
                  • > говно из <csth> обязано высираться в неймспейс std::, а в глобальный неймспейс — не обязано (на усмотрение компилятора);
                    > из <sth.h> — наборот: в глобальный неймспейс обязано, в std:: — как компилятор решит.

                    Спасибо. Не знал.
                    «Я все языки программирования изучаю по Говнокоду» ⓒ
                    https://govnokod.ru/27650#comment670193
                    Ответить
        • А почему так?
          Ответить
          • Неконсистентные размеры регистров/переменных и округления.

            З.Ы. Выше есть дизасм и его разбор.
            Ответить
            • Для дабла понятно. А тут лонг дабл и поведение меняется при замене <cmath> на <math.h>.

              В <math.h> синус и косинус определены как функции дабла, а в <cmath> перегрузка?
              Ответить
              • Ну да, в сишке это просто даблы, если ты не юзаешь дженерики из tgmath.
                Ответить
                • Кстати, в <math.h> есть fabsl, sincosl, sinl, cosl, tanl, asinl, acosl, atanl, atan2l, sinhl, coshl, tanhl, acoshl, asinhl, atanhl, expl, logl и т. п. Нужно только суффикс не забывать.
                  Ответить
                  • Это для lолечек функции? uwu
                    Ответить
                    • Это long. А tg в tgmath это type generic а не то, что вы подумали.
                      Ответить
                      • А что такое тогда «h»? hentai? Это косинус извращенца?
                        Ответить
                        • Это косинус особых людей, которым зачем-то понадобились тригонометрические функции мнимого угла.
                          Ответить
                          • Хорошо, что я в школе не учился и моя голова не забита косинусами, хуёсиносами и прочим неприменимым в жизни говном.
                            Ответить
                            • А как ты будешь шляпу из лужи доставать куском проволоки согнутым в форму интеграла, если ты не знаешь, как выглядит интеграл?
                              Ответить
                      • А что мы могли подумать? Тангенс, «Telegram», «Turbo Gears», ISO-код Того, ISO-код таджикского языка?
                        Ответить
                        • > ISO-код Того
                          > ISO-код таджикского языка

                          Какое удобство идентификации )))
                          Ответить
                          • Добро пожаловать в стандарты!

                            uk — ISO-код Соединённого Королевства, ISO-код украинского языка.
                            Ответить
                            • われね
                              ソシッン

                              Ещё где-то Eukaryot приводил подобные штучки.

                              Вот нахуя так делать-то??? Нахуя одинаково делать разное и совсем непохожее блять?????
                              Ответить
                            • Идём дальше!
                              am — ISO-код Армении, ISO-код амхарского языка (Эфиопия).
                              ar — ISO-код Аргентины, ISO-код арабского языка.
                              af — ISO-код Афганистана, ISO-код африкаанса.
                              eu — ISO-код Евросоюза, ISO-код баскского языка (самоназвание euskara).
                              be — ISO-код Бельгии, ISO-код белорусского языка.
                              cy — ISO-код Кипра, ISO-код валийского языка (самоназвание Cymraeg).
                              Ответить
                              • ga — ISO-код Габона, ISO-код ирландского языка.
                                ca — ISO-код Канады, ISO-код каталанского языка.
                                kg — ISO-код Киргизии, ISO-код языка конго.
                                La — ISO-код Лаоса, ISO-код латинского языка.
                                sr — ISO-код Суринама, ISO-код сербского языка.
                                si — ISO-код Словении, ISO-код сингальского языка (Шри-Ланка).
                                sl — ISO-код Сьерра-Леоне, ISO-код словенского языка.
                                tt — ISO-код Тринидада и Тобаго, ISO-код татарского языка.
                                tk — ISO-код Токелау, ISO-код туркменского языка.
                                ch — ISO-код Швейцарии, ISO-код языка чаморро (Полинезия).
                                sv — ISO-код Сальвадора, ISO-код шведского языка.
                                et — ISO-код Эфиопии, ISO-код эстонского языка.
                                Ответить
        • Какой багор )))
          Ответить
    • Да это же самый настоящий Гейзенбаг.

      Пока мы не смотрим на результаты косинуса - они разные: http://ideone.com/euqaru.

      Если мы наблюдаем за одним из косинусов - глючит второй: http://ideone.com/rAEQym, http://ideone.com/sZqrPA

      Но как только мы начинаем наблюдать за двумя косинусами сразу - баг пропадает: http://ideone.com/kmCqZK.

      Видимо сказываются квантовые эффекты.
      Ответить
      • Видимо в некоторых крестоблядских языках вещественный тип по умолчанию - это не 10-байтовый. Отсюда и проблемы.
        Ответить
        • Нет Тарас, просто крестоблядские языки заточены под квантовые процессоры, поэтому на них и наблюдаются данные эффекты.
          Ответить
          • Если копнуть историю, то крестоблядские языки заточены всё-таки под PDP-11. Поэтому когда кто-то говорит, что С++ "ближе к железу", чем какой-либо другой коренной язык, то у меня возникает ощущение, что я разговариваю с долбоёбом.
            Ответить
            • Ты хочешь сказать, что PDP-11 не железо?
              Ответить
              • В дровах Ferruma ничтожно мало.
                Ответить
              • Да просто даже CL раза этак в три ближе к железу, чем C.
                Сам посмотри:
                http://www.gamedev.ru/files/images/66384_1303576956_screen.png
                Ответить
                • Тонко.
                  Ответить
                • Ой, уморил-с, однако!
                  Ответить
                  • А решетки вроде запретили в никах?
                    Ответить
                    • Да, после известного случая с файками Вебкилла запретили.
                      Ответить
                      • Вот пидар. Что за случай?
                        Ответить
                        • Раньше здесь был разрешён почти весь Юникод (за исключением непечатаемых символов типа перевода строки).

                          Потом один шутник создал пародию на юзера Webkill, заменив в юзернейме латинскую «e» на русскую «е». Потом кто-то создал похожую учётку с украинской «і» вместо латинской «i». И пошло-поехало...

                          Чтобы прекратить поток поддельных учёток, Страйкер решил оставить только латиницу, цифры и ещё пару символов.
                          Ответить
                          • С такой же логикой нужно запретить буквы "l" и "I", чтобы исключить файки золотого хуя.
                            Ответить
                            • Ага. Давайте в issues внесём предложение?
                              Ответить
                            • У них ширина и высота разная, когда рядом, лучше заметно: Il
                              Ответить
                              • Напомнило анекдот. У наркомана на улице спрашивают:
                                –— Как найти площадь Ильича?
                                —– Чтобы найти площадь Ильича, нужно длину Ильича умножить на ширину Ильича.
                                Ответить
                          • Интересно, чья ты файка, раз ты такой олдфаг.
                            Ответить
                • показать все, что скрытоvanished
                  Ответить
            • показать все, что скрытоvanished
              Ответить
        • Double-precision floating-point is an IEEE 754 standard for encoding binary or decimal floating-point numbers in 64 bits (8 bytes).
          Ответить
          • There are three binary floating-point basic formats (encoded with 32, 64 or 128 bits) and two decimal floating-point basic formats (encoded with 64 or 128 bits). The binary32 and binary64 formats are the single and double formats of IEEE 754-1985. A conforming implementation must fully implement at least one of the basic formats.

            The standard does not require an implementation to support extended or extendable precision formats.

            Так что 80 битная интелоарифметика идет лесом.
            Ответить
            • Чего, 128 бит плавающей запятой?
              Ответить
              • Ага. Числа четверной точности, которых я никогда не встречал ;)
                Ответить
                • Лолшто? SSE/AVX и тд
                  Ответить
                  • Пруф в студию. ЕМНИП в SSE как были флоаты и даблы, так и остались, только их количество в одном регистре увеличили в последних версиях.
                    Ответить
                • А кто видел HalfFloat? На видяхах используют.
                  Ответить
        • >в некоторых крестоблядских языках вещественный тип
          употребляет вещества.
          Ответить
        • В некоторых языках нужно использовать long double. Но не все конпеляторы его реализуют. Проверять нужно, в общем.

          https://ideone.com/oq2JMX
          https://ideone.com/kNTAxn

          Гэцэцэ и шланг на x86_64 выделяют по 128 бит. Возможно, внутри они используют 80-битного питуха, выровненного до размера машинного слова.
          Ответить
      • оптимизаторопроблемы...
        Ответить
      • Паrни. Поплюсуйте тред что-ли, а то утонет. Годное обсуждение вышло.
        Ответить
    • Использую gcc 4.7.2 и невозможное невозможно. Что я делаю не так?
      Ответить
    • А всего-то надо переопределить операторы ~= (примерно равно) и ~!= (примерно не-равно).
      Ответить
      • >~!=
        Кресты в отличии от хаскеля не умеют в перегрузку операторов настолько хорошо
        Ответить
        • Во видно мин уснул "знаток".
          Ответить
        • Нельзя оператор - напиши функцию, какая разница.
          Ответить
      • Насколько примерно?
        Ответить
      • Надо оператор == объявить устаревшим и ненадёжным, а вместо него завести операторы теоретически_равно и наверняка_равно. Имплементация наверняка_равно будет перед сравнением приводить всё к HalfFloat, для надёжности.
        Ответить
    • На clang
      Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
      Target: x86_64-apple-darwin12.2.1

      не воспроизводится.
      Ответить
      • Ну оно и на gcc не всегда воспроизводится...

        Попробовал на clang - по дефолту он сгенерил сравнение через SSE регистры, тем самым подрезав оба аргумента до 64битных. Если же дать ему -march=i386, то он делает как гцц, но временную переменную оформляет не как 64 битный double, а как 80 битный, поэтому тоже не багует.
        Ответить
    • Теги в говнокоде не нужно писать.
      Ответить
    • тест
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • Какой багор )))
      Ответить
    • Неувядающая классика.

      #косинус #синус #плавающий питух #float
      Ответить

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