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

    +159

    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
    function key_exists_check($key,$ar)
    {
            if (empty($key))
                    $key = '0.001';
    
            strval($key);
    
            if (array_key_exists($key,$ar))
                    while (array_key_exists($key,$ar))
                            $key=strval(floatval($key)+0.001);
    
            return strval($key);
    }

    Другого решения не вижу - задача при добавлении в массив - делать уникальные ключи, которые типа float.

    Запостил: atarix12, 12 Мая 2010

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

    • Я что не пойму. зачем проверять на существование ключа. Мне кажется достаточно только увеличивать значение ключа на 0.001. причем не передавать его в параметрах. Сделать аналог автоинкремента. Ну это так на вскидку
      Ответить
      • Просто увеличить и перетереть часть массива с таким же ключом... Замечательно!
        Ответить
        • часть == 1 элемент. Армия не заметит потери бойца... Особенно под номером, к примеру, 0.926000001 (учтем округления формата 64xIEEE) )))
          Ответить
      • Он в сущности так и сделал, просто как-то странно :)
        В большинстве случаев цикл не будет отрабатывать больше одной итерации.
        Другое дело что float-ключи - это жесть, конечно.
        Ответить
        • ну вот во флоат и дело. Если правильно понимаю логику автора, то: нужно же было хранить флоаты, причем с точностью до 10е-3 оО
          а раз [] инкрементирует на единицу, а не на тысячную, поэтому изворачиваемся.
          Ответить
          • Видимо автор хотел вечный ключ, а про "всякие" потери точности не догадывался... Он считал его всесильным и бесконечным...
            Ответить
            • в чем вечность? СУБД на 1000000000000000 записей? даа, только для пхп с его memory_limit это дело в уме(рам) держать
              Ответить
      • все равно тогда где-то хранить "последний индекс"
        Ответить
    • function addElementunderUnicKey($el,&$array)
      {
        static $key = 0.0;
        $array[$key]=$el;
        $key+=0.001;
      }
      Ответить
    • А не проще ли использовать обычные (целочисленные) ключи массивов и при необходимости просто делить их на 1000?
      Ответить
    • обычные ключи, путем []. floatval() при необходимости. Или задача еще в чем то?
      Ответить
    • "делать уникальные ключи, которые типа float."

      и это само по себе уже есть говно. можно конечно правильное сравнение флоатов с epsilon делать, но все равно гавно.

      "задача при добавлении в массив"

      и это пахнет ассоциативным массивом. разве в PHP такого нет??
      Ответить
      • > правильное сравнение флоатов с epsilon делать
        во первых, в пхп, если я правильно курил мануал, скалярное значение (число или строка, не обьект и не массив) внутренне хранится в нескольких значениях (строка, число), и есть указатель типа на нее, а приведение типов есть всего "переключение" этого указателя, поэтому внутренне не должно быть сбоев. Эпсилон-сравнение годится только в случае явного сравнивания, нет?

        > то пахнет ассоциативным массивом. разве в PHP такого нет?
        любой массив в пхп, даже с целочисленными ключами, ассоциативен
        Ответить
        • > любой массив в пхп, даже с целочисленными ключами, ассоциативен

          так какого?? ... а ну да - гавнокод ;)

          > внутренне хранится в нескольких значениях (строка, число), и есть указатель типа на нее

          ага. ну это они похоже прямо из перла переписали.

          > Эпсилон-сравнение годится только в случае явного сравнивания, нет?

          все сводится к тому как сделана strval(): если она округляет, то это может работать. если нет, то есть шанс что какое N*0.001 строчкой на конце получит 00000Х или 99999Х потому что некоторые числа во флоате просто невозможно представить точно. как раз для этого и нужно эпсилон сравнение.
          Ответить
          • > как сделана strval()
            она вообще ничего не делает, кроме того, что меняет внутренний указатель типа. Округлять к "ближайшему двоичному дробному" будут арифметические операторы, а если потом наивно делать ==, тут-то и можно жестко пролететь
            Ответить
            • я стормозил не описал. я по перлу знаю че они делают, так мне было как бы очевидно.

              но тем не менее я ошибся в одном: PHP округляет при конвертации из строки. и при конвертации используется точность (precision) указаная в php.ini (N.B. Перл сам не округляет, sprintf()ом надо просить.)
              function key_exists_check($key,$ar)
              {
                      if (empty($key))
                              $key = '0.001';
              
                      strval($key);
                      /* ничего не делает: операций с параметром не делается, возвращенная безымянная переменная подбирается GC.
                         http://svn.php.net/viewvc/php/php-src/trunk/ext/standard/type.c?revision=296679&view=markup , строка 181  */
              
                      if (array_key_exists($key,$ar))
                              while (array_key_exists($key,$ar))
                                      $key=strval(floatval($key)+0.001);
                     /* шаг 1й: floatval(), если параметр строка то вызывает strtod() */
                     /* шаг 2й: strval(), если параметр double то вызывает sprintf("%.*G", precision_from_php_ini, arg ); и возвращает эту строку */
                     /* смотреть http://svn.php.net/viewvc/php/php-src/trunk/Zend/zend_operators.c?revision=299280&view=markup функции convert_to_string() & convert_to_double() */
              
                      return strval($key);
              }


              вообщем оно совершенно случайно может и работать, если в php.ini точность стоит маленькая.

              Edit1: мля я стормозил опять. так как strval() ничего не делает то на самом деле может поехать точность. floatval() будет получать копию того же самого что перед этим интерпретатор посчитал как floatval($key)+0.001
              Ответить
              • кажись точность поедет в этом самом floatval($key)+0.001, и извращения со strval() именно ТУТ не приводят к эффекту... Эффект будет после возвращения из функции
                Ответить

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