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

    +115

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    8. 8
    9. 9
    Function isEQ(x,y : Real) : Boolean;
    Begin
    if(x = y) Then isEQ := True Else isEQ := False;
    End;
    
    
    Begin
    {...}
    End.

    Не выспался...

    Запостил: x0wl, 18 Июля 2010

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

    • Паскалист бы написал
      isEQ := (x = y);

      А для вещественных лучше так:
      isEQ := (x - y) = 0;

      А c учётом вычислительных погрешностей:
      isEQ := abs(x - y) < eps * abs(x);
      (x = 0 особый случай).
      Здесь eps определено так, что 1 + eps = 1 в логике компилятора.

      Чувствую, сейчас кто-нибудь прибежит и крикнет: «Баян!»
      Ответить
      • isEQ := (x - y) = 0;
        - это не сработает.
        Нужно так:
        isEQ := (x - y) < некоторое_малое_значение;
        Ответить
        • Строчкой ниже я об этом написал: abs(x-y) < некоторое_малое_значение (именно abs, иначе не получится). Если взять константу, то числа с малым показателем будут почти всегда равны, поэтому некоторое_малое_значение должно быть пропорционально величине сравниваемых чисел.

          Пару раз наступил на грабли из-за машинного эпсилон, после чего сравниваю именно таким способом.
          Ответить
      • Дело в том, что это универ. Я сишник и повершельщик
        Ответить
    • ну и еще, как вам примерно такое?
      isEQ := (x xor y) = 0;
      Ответить
      • Для вещественных не пойдёт, а для целых — круто!
        Ответить
        • если думать, что вещественные тоже набор битов, то теоретически прокатило бы. практически, действительно, нет - и не только на делфях
          Ответить
          • Для типов, укладывающихся в машинные слова прокатит только после принудительного изменения типа (в делфях/BP — move или запись с вариантными полями, в сях — memcpy или union). Пример:
            type hack = record
                case integer of:
                    1: f: Single;
                    2: i: Longint;
                end;
            end;
            
            var x, y: hack;
            ...
            isEQ := (x.i xor y.i) = 0;

            Или через указатели на память:
            type hack = ^Longint;
            ...
            isEQ :=  hack(@x)^ xor hack(@y)^ = 0;

            Жаль, не будет работать на значениях, только на переменных.
            Ответить
            • P.S. Не копируйте этот код! Он ничем не лучше прямого равенства. На практике он почти наверняка будет выдавать false.
              Ответить
              • Внезапно возникла идейка. Сравнивать порядки чисел и все биты мантиссы, кроме последнего. Тогда машинное эпсилон будет учтено. То есть после сравнения с помощью and вырезать младший бит мантиссы.
                Ответить
                • то есть опять же округление?
                  Ответить
                  • Вы так говорите об округлении, как будто это что-то плохое. На самом деле зависит от задачи. Теоретически округление может оказать и медвежью услугу. Вещественные числа ведь применяют в реализациях численных методов?
                    Ответить
                    • нет, я не говорю, что это плохо, я говорю только о том, что идейка не особо революционна
                      Ответить
                      • Согласен, что не ново, но работать будет побыстрее, чем abs(x-y) < epsilon.
                        Сравнение с округлением может споткнуться в случае, когда порядки разные, например, что-то типа 2 и 1,(9) или нормализованное число и денормализованное.
                        Ответить
                        • вряд ли оно будет быстрее, чем родное "x=y", которое транслируется всего в cmp x,y
                          так что предлагаю не задумываться о сравнении, а оставить на шаге битовых операций для вещественных чисел
                          Ответить
            • вот так мы расширили понятие битовых операций на множество вещественных чисел, подобно тому, как понятие логарифмов и корней расширяет понятие степени вне н-кратного умножения на себя.

              интересно, это может иметь какой-нибудь практический смысл, или судьба совершенных чисел повторится - красиво, но бесполезно?
              Ответить
              • Битовый сдвиг мантиссы и битовый сдвиг порядка приводят к разным эффектам, поэтому их надо выполнять отдельно, если мы, конечно, не пишем генератор псевдослучайных чисел. Страшно представить, что будет, если биты мантиссы въедут в биты порядка или наоборот. Аналогично и с другими операциями.
                Ответить
                • псевдослучайная последовательность - закономерная последовательность, закономерность которой неочевидна. То есть, это опять зависит от интеллекта индивида: нам с вами какая то последовательность может показаться случайной, а какой-нибудь гений выведет закономерность и будет на эту последовательность фыркать
                  Ответить
                  • Вот именно поэтому обычные псевдослучайные числа не годятся для криптографического метода «одноразовых блокнотов». Из-за применения псевдослучайности вместо случайности он становится потенциально вскрываемым.
                    Ответить
                    • вообще сложно сказать, что является "истинной" случайностью. Существует же некая теория детерминированности реальности, из которой следует, что даже классически предлагаемый способ бросать монетку - тоже будет генерировать не "случайные" "биты", а "псевдослучайные", пусть и с лучшим разбросом, а так же и более интересные выводы, такие, как
                      достаточно мощный компьютер может предказать будущее
                      время лишено мистицизма - в том утверждении, что "никто не знает, что будет" - и, возможно, все "существующее в будущем" - "уже" существует давно
                      Ответить
                    • и вообще, вся наука криптология основывается на достаточно субьективных понятиях типа "сложно (но можно)догадаться" и "долго считать", что значит, что в какой то момент развития вычислительных технологий она может крупно обосраться дискредитировать себя

                      но это уже уводит мысль в направлении о копирастии, что информация должна быть свободной )))
                      Ответить
                      • Криптология основывается на вполне объективных просчетах количества вычислений, необходимого для взлома (в зависимости от длины ключа).
                        И получается, что при достаточно длинном ключе не хватит не то, что времени на перебор, а еще и тупо энергии, даже если злоумышленник умудрится запитать свой мегакомп от Солнца. Тут уж как технологии не развивай - не вскроешь.
                        А еще можно вспомнить о "сроке годности" информации - через год взлома перебором скрытая информация может запросто потерять свою ценность.
                        Ответить
                        • по моему, вы переоцениваете количество вычислений...
                          Ответить
                          • http://www.intuit.ru/department/security/mssec/6/
                            Обратите внимание на раздел "Оценка предельных мощностей взлома" - энергии Солнца хватит лишь на 250-разрядный ключ.
                            Ответить
                            • существует так же мизерная вероятность, что я подберу ключ с первого раза )
                              Ответить
                              • Совсем уж мизерная, особенно для ключа в пару килобайт ))
                                Ответить
            • ^Int64 тогда уж, generic Real у багланда маппится в Double
              Ответить
              • Int64 лучше. У меня была просто иллюстрация.
                А для типа Extended (80 бит) придётся вводить ^array[0..9]of Byte или ^array[0..4]of SmallWord и ксорить по частям.
                Ответить
                • Количество и разнообразие костылей как бы намекает нам на порочность самой идеи, нет?
                  Ответить
                  • у меня дача на костылях держится, но это не говорит о порочности дачи
                    Ответить
                    • На такой даче никто не даст, ∴ она не нужна
                      Ответить
                      • За такой подход тоже, что говорит о его непорочности => дача тоже непорочная
                        Ответить
            • а с учетом погрешности
              type hack = ^Longint;
              var t: longint;
              ...
              t := hack(@x)^ - hack(@y)^;
              if (t < 0) then t := -t;
              isEQ := t < (1 shl n); // n - точность. чем меньше, тем точнее. погрешность в мантиссе, а знак и экспонента должны совпадать.
              ну случай с нулем отдельно нужно обрабатывать.
              и на значениях работать будет ;)
              Ответить
          • Но на практике такое сравнение будет абсолютно бесполезным по причине машинного эпсилон. Например, 10 + 1 / 2 может оказаться не равным 10.5.
            Ответить
            • вообще битовые операции имеют только битовый смысл - для всяких там флагов. Алгебраического смысла они не несут, за исключением всяких применений и побочных эффектов - вот как в сравнении исключением.
              я о том, что, например, 2 and 3 не представляется таким же понятным действием, как, например 2 + 3. тогда как даже тригонометрические функции хорошо представимы соотношением углов и сторон треугольника, комплексные числа - как двумерная числовая величина, и т.д.
              Ответить
              • А как же умножение и деление на 2 при помощи "<<" и ">>"? Очень даже алгебраичное применение и применяется такой способ очень часто.
                Ответить
            • но мы же сравниваем битовое представление чисел, а из за машинного эпсилон, именно битовое 10.5 может оказаться неравным результату выражения 10 + 1 / 2

              но для хора вещественных - самое то, что надо, браво инканус!
              Ответить

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