Кресты / Говнокод #12138 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  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 igumnovf, (Updated )

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

  • http://ideone.com/0mEBvi
    Ты думал для нас Америку открыть?
    Тут язык не причем. Это проблема более капитальная на уровне чисел с плавающей точкой и в общем случае не разрешимая.
    Ответить
  • Разобрался с причиной бага. Внимательно смотрим на дизасм:
    .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 один из косинусов стал менее точным.
    Ответить
        • Так фиксили баг в пыхе, в результате которого он вис на парсинге специально сформированного числа.

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

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

      P.S. Сишный аналог, кстати, long double. Но он в разных реализациях компилятора разный. Он не обязан быть 80-битным.
      Ответить
      • - #include <cmath>
        + #include <math.h>

        Вот это реально сильное колдунство.
        Ответить
          • Нет. "cmath" - это типа для крестовиков и нужно писать std::, "math.h" - для сишников. К примеру, "ISO" выебнется и будет cmath использовать.
            Ответить
            • Разве <cнечто> в С++ это не тоже самое, что <нечто.h> в няшной (ну с поправкой на std)?
              Ответить
              • Ну вот тут оказалось, что ещё с поправкой на перегрузку. Гэцэцэшных генериков для сишки не было, когда придумывали <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 и т. п. Нужно только суффикс не забывать.
                Ответить
                  • Это long. А tg в tgmath это type generic а не то, что вы подумали.
                    Ответить
                      • Это косинус особых людей, которым зачем-то понадобились тригонометрические функции мнимого угла.
                        Ответить
                        • Хорошо, что я в школе не учился и моя голова не забита косинусами, хуёсиносами и прочим неприменимым в жизни говном.
                          Ответить
                          • А как ты будешь шляпу из лужи доставать куском проволоки согнутым в форму интеграла, если ты не знаешь, как выглядит интеграл?
                            Ответить
                    • А что мы могли подумать? Тангенс, «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. Поэтому когда кто-то говорит, что С++ "ближе к железу", чем какой-либо другой коренной язык, то у меня возникает ощущение, что я разговариваю с долбоёбом.
          Ответить
      • 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 битная интелоарифметика идет лесом.
          Ответить
            • Ага. Числа четверной точности, которых я никогда не встречал 😉
              Ответить
                • Пруф в студию. ЕМНИП в SSE как были флоаты и даблы, так и остались, только их количество в одном регистре увеличили в последних версиях.
                  Ответить
      • >в некоторых крестоблядских языках вещественный тип
        употребляет вещества.
        Ответить
      • В некоторых языках нужно использовать long double. Но не все конпеляторы его реализуют. Проверять нужно, в общем.

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

        Гэцэцэ и шланг на x86_64 выделяют по 128 бит. Возможно, внутри они используют 80-битного питуха, выровненного до размера машинного слова.
        Ответить
    • Паrни. Поплюсуйте тред что-ли, а то утонет. Годное обсуждение вышло.
      Ответить
  • Использую gcc 4.7.2 и невозможное невозможно. Что я делаю не так?
    Ответить
  • А всего-то надо переопределить операторы ~= (примерно равно) и ~!= (примерно не-равно).
    Ответить
  • На 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 битный, поэтому тоже не багует.
      Ответить
  • долбоёбина флоаты сравнивает
    Ответить
  • Неувядающая классика.

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

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

Помни, guest, за тобой могут следить!

    А не использовать ли нам bbcode?


    8