На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (2) 1 [2]  все  ( Перейти к последнему сообщению )  
> В буфере появляется лишний символ
    Majestio, ты что-то путаешь. У std::bitset<> нет конструктора, принимающего массив байт. Его конструкторы, принимающие строки в том или ином виде, как обозначение бита рассматривают каждый символ, а не бит. Т.е. можно получить std::bitset<8>("00110110").to_ulong() == 0b110110ul (или std::bitset<8>(0b110110ul).to_string() == "00110110"), но не или std::bitset<8>("01").to_ulong() == 0b00000001ul
      Qraizer, да - всё верно! Перепутал я малёха. Свой пример с std::bitset я исправил.
        tumanovalex, кстати, я тоже когда-то делал для себя заготовки для работы с битами без STL - ознакомься :) Правда там есть два недостатка: нет проверок индекса на предмет выхода за пределы массива, и нет определения порядка битов в байте для целевой архитектуры. Но это уже всё можно добавить, при желании.
          В общем, если кому интересно, то универсальный код преобразования обоих типов ...э-э-э, типов в битовый вид.
          ExpandedWrap disabled
            #include <limits>
            #include <concepts>
            #include <cmath>
            #include <bit>
             
            /* преобразование целых в строку */
            std::string TypeToBin(std::integral auto source)
            {
              int const   size = std::numeric_limits<unsigned char>::digits * sizeof(source);       // размер в битах
              std::string str(size, ' ');
             
              for (int i = size - 1; i >= 0; i--)
              {
                str[i] = (source & 1) + '0';
                source >>= 1;
              }
              return str;
            }
             
            /* преобразование вещественных в строку (для не IEEE-совместимых не тестировалось) */
            std::string TypeToBin(std::floating_point auto source)
            {
              std::string    buf;
              int            power;                 // порядок source
              const auto    &properties   = std::numeric_limits<decltype(source)>{};
              const unsigned shiftedPower = static_cast<unsigned>(properties.max_exponent - properties.min_exponent);
             
              buf.reserve(properties.digits + std::bit_width(shiftedPower) + 3);   // + точка, 'b' и знак
              buf = std::signbit(source) + '0';     // первым знак
              if (!std::isfinite(source))           // проверка на спец.форматы NaN и inf
              {
                // сначала избавиться от порядка, но сохранить мантиссу (на случай NaN особенно)
                // используем бесконечность как образец в памяти ...
                decltype(source) pattern = properties.infinity();
                const char (&nanByte)[sizeof(pattern)] = reinterpret_cast<const char (&)[sizeof(pattern)]>(pattern);
                      char (&srcByte)[sizeof(source)]  = reinterpret_cast<      char (&)[sizeof(source)]> (source);
             
                // ... и обрабатываем source побайтно, стирая порядок ...
                for (int i = 0; i < sizeof(nanByte); ++i)
                  srcByte[i] ^= nanByte[i];
                // ... а затем заменяем его на несмещённый порядок 0
                // это также учтёт явный старший бит, если он есть, т.к. XOR применяется дважды
                // + нам пофик на endianess, т.к. он одинаковый для source и pattern
                pattern = 1;
                for (int i = 0; i < sizeof(nanByte); ++i)
                  srcByte[i] ^= nanByte[i];
                source = abs(source);               // теперь можно вычислять модуль, в source не спец.формат
                // максимальный порядок спец.форматов с учётом его разрядности в типе source, т.к. реализации
                // любят в FP_ILOGBNAN совать просто MAX_INT
                power = FP_ILOGBNAN & (std::bit_ceil(shiftedPower) - 1);
              }
              else                                  // для остальных форматов всё значительно проще
              {
                source = abs(source);               // модуль можно сразу
                power = logb(source);               // порядок
                source= ldexp(source, -power);      // чистая мантисса (с порядком 0)
                // использовать frexp() нежелательно, т.к. она возвращает мантиссу, сдвинутую в [0.5, 1)
                // что уменьшает точность на бит и требует специальной дополнительной обработки её и порядка,
                // особенно рядом с std::numeric_limits<>::denorm_min()
              }
              /* обработать мантиссу */
              for (int i = 0; i < properties.digits; ++i)
              {
                buf       += static_cast<char>(static_cast<int>(source));
                source    -= buf.back();
                buf.back()+= '0';
                source    *= static_cast<decltype(source)>(2);
              }
              buf.insert(2, 1, '.');                // добавить точку в buf
             
              // обработать порядок
              buf += 'b';
              // power хранит меньшую разрядность, чем способен его тип, например 12 для IEEEшного double,
              // поэтому имеет смысл отрезать от него только нужное количество младших бит
              buf += TypeToBin(power).substr(std::numeric_limits<decltype(power)>::digits - 1 // знак уже учтён
                                           - std::bit_width(shiftedPower / 2));             // а порядок смещён
             
              return buf;
            }
          Требует C++20. Вид битового ...э-э-э, вида вещественных сомнителен. Мне тоже не нравится, но так единообразнее с видом целых. Кому интересно переделать, милости прошу. Знак вещественного просто 0 или 1, знак порядка аналогично. Точка в мантиссе соответственно лежит после второго бита. Мантиссы спец.форматов по возможности разгребаются, но хорошо потестировать поленился. Бесконечности и нечисла распознаются по старшим 011 в порядке, отличаются друг от друга естественно мантиссой. Знаки также распознаются правильно, даже для нуля.
          Сообщение отредактировано: Qraizer -
          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
          0 пользователей:


          Рейтинг@Mail.ru
          [ Script execution time: 0,0321 ]   [ 16 queries used ]   [ Generated: 15.06.25, 12:18 GMT ]