На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Преобразование двоичного числа в десятичное со знаком
    В Калькуляторе Windows попробовал перевести "-1" в двоичное представление и получил
    1111111111111111111111111111111111111111111111111111111111111111. Затем опять попробовал перевести в десятичное, получил 18446744073709551615. Хотел бы сделать программу, которая правильно переводила бы двоичное представление в десятичное. Например, указал двоичное представление 1011111111111111111111111111111111111111111111111111111111111111, получил бы правильное целое число со знаком, а не 13835058055282163711.
    Попробовал сам написать программу:
    ExpandedWrap disabled
      #include <iostream>
      #include <string>
       
      using namespace std;
       
      int strtoint(string sbit) {
        int i, multi = 1, number = 0;
        for(i = sbit.length(); i; i--, multi *=2 ) {
          if(sbit[i-1] == '1')
            number += multi;
        } //for
        return number;
      }
       
      void main(int argc, char* argv[]) {
        int narr[] = {-1, 1, -2, 2, -4, 4, -8, 8, -16, 16, -64, 64, -128, 128, -32767, 32767}, i = 0, j = 1, num;
        char sbit[33];
        string str, strnew;
        while(narr[i]) {
           sbit[0]  = 0;
           sbit[32] = 0;
          _itoa(narr[i], sbit, 2);
          str = sbit;
          while(str.length() < 32) {
            str.insert(0, "0");  
          }
          strnew = str;
          if(strnew[0] == '1') {
            for(j = 0; j < strnew.length() - 1; j++) {
              if(strnew[j]=='1')
                strnew[j] = '0';
            } // for j
            if(strnew[strnew.length()]=='1')
              strnew[strnew.length()] = '0';
            num = -1 * strtoint(strnew);
          }  // if(strnew[0] == '1'
          else {
            num = strtoint(strnew);
          }
          cout <<  narr[i] << "\t" << num << endl;
          i++;
        } // while
        cin.get();
      }

    В массив narr могут добавляться другие знчения, поэтому хотелось бы не задавать жестко число элементов в нем. Вижу следующие ошибки:
    1. Неправильно прохожу массив narr, появляются мусорные значения. Хотелось бы понять, как правильно проходить массив при такой его инициализации.
    2. Неправильно работаю с дополнительным битом, полученные значения для отрицательных чисел неверны.
    Подскажите,пожалуйста, как мне правильно обойти массив и правильно конвертировать дополнительный код для отрицательного числа.
      1.
      ExpandedWrap disabled
        long len = sizeof(narr)/sizeof(narr[0]);
        for ( long i = 0; i < len; i++ )
        Изучите уже наконец битовую арифметику:

        ExpandedWrap disabled
          long strtoint(string sbit)
          {
            int i, len;
            long number=0;
            len=sbit.length();
            for(i=0; i<len; i++)
            {
              number<<=1;
              if(sbit[i] == '1') number |= 1;
            }
            // Расширение знакового бита
            // Нужно если строка содержит не все биты (длина строки не равна разрядности числа)
            // "011" - будет 3, "11" - будет -1
            if(len!=sizeof(number)*8)
            {
              number<<=sizeof(number)*8-len;
              number>>=sizeof(number)*8-len;
            }
            return number;
          }
        Сообщение отредактировано: cppasm -
          cppasm, там 65 по 1 =) long мала будет, в MSVC вообще long = int
            Дык bitset! И нафиг строки и long'и.
              1...1 - это так называемый дополнительный код числа. Для перевода в десятичную нужно сделать так:
              1 - конвертировать все биты: 0->1, 1->0
              2 - прибавить 1 в двоичной системе.
              3 - переводить в десятичную
              4 - поставить спереди минус.
                Цитата ss @
                Дык bitset! И нафиг строки и long'и.



                ExpandedWrap disabled
                  #include <iostream>
                  #include <bitset>
                   
                  int main ()
                  {
                      std::bitset<33> bits;
                      bits.set();
                      bits.to_ulong();
                      return 0;
                  }


                Падает =)
                Сообщение отредактировано: like-nix -
                  ExpandedWrap disabled
                    _Xoflo();   // fail if any high-order words are nonzero

                  Ты б ещё 500 бит в ulong упихать попытался <_<
                    ss, подскажите тогда как перевести из bitset в десятичную систему или хотябы в строку число десятичной системы

                    Добавлено
                    Кстати у буста тоже есть bitset, там функционала побольше

                    Добавлено
                    арефметические операции например можно выполнять, только у меня пока не получается =)

                    Добавлено
                    Делаю так

                    ExpandedWrap disabled
                      #include <iostream>
                      #include <boost/dynamic_bitset.hpp>
                       
                      int main ()
                      {
                          boost::dynamic_bitset<> x1(34), x2(34);
                       
                          x1[31] = 1;
                          x2[30] = 1;
                       
                          std::cout << x1.to_ulong() << std::endl;
                          std::cout << x2.to_ulong() << std::endl;
                       
                          boost::dynamic_bitset<> x3(34);
                          x3 = x1 - x2;
                          std::cout << x3.to_ulong() << std::endl;
                       
                          return 0;
                      }

                    А x3 всеравно = x1 =)
                    Сообщение отредактировано: like-nix -
                      Цитата like-nix @
                      ss, подскажите тогда как перевести из bitset в десятичную систему
                      перевести-то недолго - делать с этим будет нечего, кроме как осознавать, что вот тута в памяти у меня большое-большое число лежит, которое прочитать некуда :lol:
                      Цитата like-nix @
                      или хотябы в строку число десятичной системы
                      кроме как реализовывать арифметику для строк - не знаю. В HEX - там лего, там дааа, а в десятеричную...
                      Вобщем, погорячился я. :rolleyes:
                        Цитата like-nix @
                        перевести-то недолго - делать с этим будет нечего, кроме как осознавать, что вот тута в памяти у меня большое-большое число лежит, которое прочитать некуда

                        :) я сам написал не подумав. Учитывая что все в компе в двоичной системе хранится :lol:

                        Добавлено
                        битсеты вполне могут подойти главное найти нормальный способ представления числа в другие системы счисления. Я сейчас смотрю библиотеку crypto там вроде тоже можно с большими числами работать.
                          Цитата like-nix @
                          cppasm, там 65 по 1 =) long мала будет, в MSVC вообще long = int

                          Там 64 бита, а не 65. long long (или __int64 на крайний случай) хватит.

                          Добавлено
                          Цитата LaptevVV @
                          1...1 - это так называемый дополнительный код числа. Для перевода в десятичную нужно сделать так:
                          1 - конвертировать все биты: 0->1, 1->0
                          2 - прибавить 1 в двоичной системе.
                          3 - переводить в десятичную
                          4 - поставить спереди минус.

                          Во первых это называется инвертировать, а во-вторых наоборот всё делать надо.
                          Отрицательное число - это инверсия положительного плюс 1.
                          Соответственно надо вычесть единицу и потом инвертировать, к полученному приписать спереди минус.
                          Хотя по сути это одно и то же получается.
                          Сообщение отредактировано: cppasm -
                            Строго говоря, Стандарт допускает любое из 3-х представлений отрицательных: прямое, обратное и дополнительное.
                            Цитата 3.9.1 Fundamental types
                            7. Types bool, char, wchar_t, and the signed and unsigned integer types are collectively called integral types.43) A synonym for integral type is integer type. The representations of integral types shall define values by use of a pure binary numeration system.44) [Example: this International Standard permits 2’s complement, 1’s complement and signed magnitude representations for integral types. ]

                            43) Therefore, enumerations (7.2) are not integral; however, enumerations can be promoted to int, unsigned int, long, or unsigned long, as specified in 4.5.
                            44) A positional representation for integers that uses the binary digits 0 and 1, in which the values represented by successive bits are additive, begin with 1, and are multiplied by successive integral power of 2, except perhaps for the bit with the highest position. (Adapted from the American National Dictionary for Information Processing Systems.)
                            Т.о. декларируется двоичная система счисления для репрезентации значений целых типов, у которых знаковый бит, если он есть, самый старший. Но вот как именно он вносит свой вклад, не декларируется.

                            Добавлено
                            Это C++. То же для C:
                            Цитата 6.2.6.2 Integer types
                            2. For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit. There need not be any padding bits; there shall be exactly one sign bit. Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type (if there are M value bits in the signed type and N in the unsigned type, then M ≤ N). If the sign bit is zero, it shall not affect the resulting value. If the sign bit is one, the value shall be modified in one of the following ways:
                            • the corresponding value with sign bit 0 is negated (sign and magnitude);
                            • the sign bit has the value -(2N) (two’s complement);
                            • the sign bit has the value -(2N - 1) (one’s complement).
                            Which of these applies is implementation-defined, as is whether the value with sign bit 1 and all value bits zero (for the first two), or with sign bit and all value bits 1 (for one’s complement), is a trap representation or a normal value. In the case of sign and magnitude and one’s complement, if this representation is a normal value it is called a negative zero.
                              В Crypto++ можно работать с очень большими числами.

                              ExpandedWrap disabled
                                    Integer i1("9999999999999999999999999999999999999999999999999");
                                    Integer i2("9999999999999999999999999999999999999999999999998");
                                    std::cout << i1 - i2 << std::endl;


                              Добавлено
                              Еще наткнулся на упоминания boost::bigint, но так и не нашел где можно его взять.

                              Добавлено
                              мысль закончу позже надо работать =)
                              Сообщение отредактировано: like-nix -
                                cppasm, Ваш код работает. А вот с битовой арифметикой у меня проблемы, никак не доходит. Ваш код
                                ExpandedWrap disabled
                                   number<<=1;
                                      if(sbit[i] == '1') number |= 1;
                                и
                                ExpandedWrap disabled
                                  if(len!=sizeof(number)*8)   {
                                      number<<=sizeof(number)*8-len;
                                      number>>=sizeof(number)*8-len;
                                    }
                                для меня не очень понятен. Если не очень сложно, прокомментируйте, пожалуйста. А как перебрать массив, чтобы не появлялись лишние значения?
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


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