【问题标题】:Changing integer to binary string of digits将整数更改为二进制数字字符串
【发布时间】:2012-01-03 13:27:36
【问题描述】:

我目前正在使用 C++ 模拟 MIPS 处理器,用于一个 comp 架构类,并且在从十进制数转换为二进制数(双向有符号数)时遇到了一些问题。直到最后一点,一切都运行良好,因为我当前的算法在 1

//Assume 32 bit decimal number
string DecimalToBinaryString(int a)
{
    string binary = "";
    int mask = 1;
    for(int i = 0; i < 31; i++)
    {
        if((mask&a) >= 1)
            binary = "1"+binary;
        else
            binary = "0"+binary;
        mask<<=1;
    }
    cout<<binary<<endl;
    return binary;
}

为了完整性,我还包括了我的其他算法。对于缺少 cmets,我深表歉意,但这很简单。

int BinaryStringToDecimal(string a)
{
    int num = 0;
    bool neg = false;
    if(a.at(0) == '1')
    {
        neg = true;
        for(int x = a.length()-1; x >= 0; x--)
        {
            if(a.at(x) == '1')
                a.at(x) = '0';
            else a.at(x) = '1';
        }
        a.at(a.length()-1) += 1;
        for(int x = a.length()-1; x >= 0; x--)
        {
            if(a.at(x) == '2')
            {
                if(x-1 >= 0)
                {
                    if(a.at(x-1) == '1')
                        a.at(x-1) = '2';
                    if(a.at(x-1) == '0')
                        a.at(x-1) = '1';
                    a.at(x) = '0';
                }
            }
            else if(a.at(x) == '3')
            {
                if(x-1 >= 0)
                    a.at(x-1) += '2';
                a.at(x) = '1';
            }
        }
        if(a.at(0) == '2')
            a.at(0) = '0';
        else if(a.at(0) == '3')
            a.at(0) = '1';
    }
    for(int x = a.length()-1; x >= 0; x--)
    {
        if(a.at(x) == '1')
            num += pow(2.0, a.length()-x-1);
    }
    if(neg)
        num = num*-1;   
    return num;
 }

另外,如果有人知道更有效地编写这些内容的任何好方法,我很想听听。我只上过两门编程入门课程,但一直在尝试不同的技术,看看我有多喜欢他们的风格。

【问题讨论】:

  • 改变效率的一个选项是一次工作 4 位,将每个 nybble 映射到相应的 4 字符字符串。这将减少字符串分配。我还会考虑以 MSB 到 LSB 的顺序生成答案,而不是反之亦然,因此您可以使用binary += pattern[nybble];。在右侧扩展字符串可能(几乎无法衡量)比在左侧有效插入的位置更有效。
  • 除非我真的需要自己进行转换,否则我会使用std::bitset 来处理转换和打印:std::cout &lt;&lt; std::bitset&lt;32&gt;(a);
  • 除了像@JonathanLeffler 所说的那样从左到右工作,我建议您预先分配整个字符串,因为您知道输出将是 32 chars。根据您的字符串实现,它可能会或可能不会有所不同,但它肯定不会受到伤害。

标签: c++ algorithm binary


【解决方案1】:

这些实际上有标准的单线。

#include <bitset>

std::string s = std::bitset< 64 >( 12345 ).to_string(); // string conversion

std::cout << std::bitset< 64 >( 54321 ) << ' '; // direct output

std::bitset< 64 > input;
std::cin >> input;
unsigned long ul = input.to_ulong();

See this run as a demo.

【讨论】:

  • @Chaos_99 那是unreasonably old。你从哪里得到的?
  • @Chaos_99 很久以前没有人能设法制作出可靠的编译器,而且没有足够的用户和测试用例来进行足够的预发布 QA。那些日子已经结束,但有些人选择留在其中。
  • 别告诉我,我宁愿早晚换。但是,如果您必须保证您的代码在 20 多年内完全一样编译,您就不能时不时地执行 apt-get upgrade。但是,让我们在这里结束。这对其他人没有帮助。
  • 令人惊讶的是,似乎没有人提到 bitset 的 to_string 将返回填充的二进制表示。显然,由于 bitset 返回的集合的二进制表示正是它应该返回的。但是,如果有人“滥用”位集将整数转换为二进制字符串表示,他们将调用输出填充。 cout &lt;&lt; bitset&lt;16&gt;(21); // outputs 0000000000010101
  • @parasrish 0x 表示十六进制,而不是二进制。 C++14 引入了以0b 开头的二进制字面量。
【解决方案2】:

替换:

if((mask&a) >= 1)

与任一:

if ((mask & a) != 0)

或:

if (mask & a)

你的问题是最后一位给你一个负数,而不是一个正数。

【讨论】:

    【解决方案3】:

    我检查了您的代码,没有发现任何错误。这是我使用的代码...

    #include <iostream>
    #include <string>
    using namespace std;
    
    int main ()
    {
      int a=1111165117;
      string binary  ("");
        int mask = 1;
        for(int i = 0; i < 31; i++)
        {
        if((mask&a) >= 1)
            binary = "1"+binary;
        else
            binary = "0"+binary;
         mask<<=1;
     }
     cout<<binary<<endl;
     system("PAUSE");         //optional if not using ideone
     return EXIT_SUCCESS;     //optional if not using ideone
     }
    

    输出将是 1001110001010110101111010011101。 我可以在 ideone 上运行它

    【讨论】:

      【解决方案4】:

      1 int 转换的代码片段,您有几个选择:

      • 将字符串转换为流并使用为流定义的运算符>>(int&) //更正 - 别介意 >:-) setbase() 流修饰符不支持 2 值作为参数
      • 使用具有基值参数的标准 C 函数 strtol()(二进制为 2)
      • 或者如果您真的想自己实现转换,请尝试以下代码:

        int BinaryStringToDecimal(string a) 
        {
            int Rslt = 0;
            int Mask = 1;
            for (int i = a.length()-1; i >= 0; --i, Mask <<= 1) {
                if (a.at(i) != '0') {
                    Rslt |= Mask;
                }
            }
            return (Rslt);
        }
        

      请注意,与您的代码相比,此代码处理负数的方式不同:在您的函数中,最高位被视为符号。如果您的函数的字符串参数中最左边的位不在位置 32(从右数),您的函数可能会产生不正确的结果。在此处建议的代码中,没有特殊的符号处理。但是,如果您得到最左边的 32 位数字字符串,则 int 结果中的 MSB 将为 == 1,整数将为负数(应为负数)

      【讨论】:

        【解决方案5】:

        为什么不能将int 转换为uint?然后很容易生成二进制字符串,因为您不必担心符号位。将二进制字符串转换为int 也是如此:将其构建为uint,然后将其转换为int

        string DecimalToBinaryString(int a)
        {
            uint b = (uint)a;
            string binary = "";
            uint mask = 0x80000000u;
            while (mask > 0)
            {
                binary += ((b & mask) == 0) ? '0' : '1';
                mask >>= 1;
            }
            cout<<binary<<endl;
            return binary;
        }
        

        当然,您可以应用上述优化,例如预分配字符串缓冲区等。

        另辟蹊径:

        uint b = 0;
        for (int i = 31; i >=0; --i)
        {
            b <<= 1;
            if (a.at(i) == '1')
                b |= 1;
        }
        int num = (int)b;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-02-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多