在C++中将数据转换为二进制

3

我写了一个将数字转换为二进制的函数。但是不知道为什么它不能正常工作,输出结果总是错误的。虽然输出结果是以二进制格式呈现的,但是对于以零结尾的二进制数,它总是给出错误的结果(至少我注意到了这一点...)

unsigned long long to_binary(unsigned long long x)
{
    int rem;
    unsigned long long converted = 0;

    while (x > 1)
    {
        rem = x % 2;
        x /= 2;
        converted += rem;
        converted *= 10;
    }

    converted += x;

    return converted;
}

请帮我修复它,这真的很令人沮丧。

谢谢!


4
因为数字已经是二进制形式,所以没必要转换,这真的很让人沮丧。你可以打印它的位,但是网上有大量的示例。 - user405725
2
你正在进行的是将二进制转换为一个看起来像二进制的十进制数,但实际上数值是错误的。 你的作业任务具体是什么? - Wooble
这不是一项作业任务。我在尝试学习一些东西。我知道数字已经是二进制的,但它们以十进制形式显示。我只想将它们显示为二进制,并且为此我需要将十进制表示转换为二进制。或者我不需要这样做吗?如果有一种方法可以将它们显示为它们的二进制表示,我真的很想看到它。谢谢。 - Lockhead
9个回答

4
使用std::bitset进行转换:
#include <iostream>
#include <bitset>
#include <limits.h>

int main()
{
    int     val;
    std::cin >> val;

    std::bitset<sizeof(int) * CHAR_BIT>    bits(val);
    std::cout << bits << "\n";

}

2
  1. 你正在颠倒位。
  2. 你不能使用x的余数作为指示器来终止循环。

例如考虑数字4。

第一次循环迭代后:

rem == 0
converted == 0
x == 2

第二次循环迭代后:
rem == 0
converted == 0
x == 1

然后你将“converted”设置为1。

尝试:

int i = sizeof(x) * 8; // i is now number of bits in x
while (i>0) {
  --i;
  converted *= 10;
  converted |= (x >> i) & 1;
  // Shift x right to get bit number i in the rightmost position, 
  // then and with 1 to remove any bits left of bit number i,
  // and finally or it into the rightmost position in converted
}

当x作为无符号字符(8位)的值为129(二进制10000001)运行上述代码时

i=8开始,无符号字符* 8的大小。在第一次循环迭代中,i将变为7。然后我们将x(129)向右移7位,得到值1。这个值被或者进入converted,它变成1。下一次迭代,我们首先将converted乘以10(所以现在是10),然后将x向右移动6位(值变为2),并将其与1 AND运算(值变为0)。我们将0和converted进行OR运算,然后仍然是10。第3-7次迭代做同样的事情,将converted乘以10,并从x中提取出一个特定的位,并将其或者进入converted。经过这些迭代,converted变为1000000。

在最后一次迭代中,首先将converted乘以10,并变为10000000,我们将x向右移动0位,得到原始值129。我们将x与1进行AND运算,这给出值为1。然后1或者进入converted,它变成10000001。


1
他没有使用剩余部分作为停止条件,我认为你的代码需要一些解释。我理解它,但我怀疑有基本C知识的人会不会理解。而且你还缺少了converted的初始化,这非常重要。 - krtek
你能解释一下最后一行吗?你使用位运算符OR、AND和右移的目的是什么?还有,第一行(sizeof(x) * 8)的目的是什么? - Lockhead
仍然有一些困难理解这个...请原谅我的无知 :P 你可以展示一个这个是如何工作的例子吗? - Lockhead
太棒了!谢谢!我现在明白了!我使用gprof进行了分析,这似乎是最好的方法。 - Lockhead

1

你做错了;)

http://www.bellaonline.com/articles/art31011.asp

第一部分的余数是二进制形式中最右边的位,但使用您的函数后,它将变为最左边的位。

您可以尝试像这样做:

unsigned long long to_binary(unsigned long long x)
{
    int rem;
    unsigned long long converted = 0;
    unsigned long long multiplicator = 1;

    while (x > 0)
    {
        rem = x % 2;
        x /= 2;
        converted += rem * multiplicator;
        multiplicator *= 10;
    }

    return converted;
}

编辑:CygnusX1 提出的代码更加高效,但我认为不够全面,建议采用他的版本。

改进:我改变了 while 循环的停止条件,因此我们可以删除在结尾添加 x 的那一行。


0

您实际上是在反转二进制数!to_binary(2)将返回01,而不是10。当初始0被截断时,它看起来与1相同。

这样怎么样:

unsigned long long digit = 1;
while (x>0) {
  if (x%2)
    converted+=digit;
  x/=2;
  digit*=10;
}

0

如果你想将数字显示为二进制,你需要将其格式化为字符串。我知道的最简单的方法是使用 STL bitset

#include <bitset>
#include <iostream>
#include <sstream>

typedef std::bitset<64> bitset64;


std::string to_binary(const unsigned long long int& n)
{
        const static int mask = 0xffffffff;
        int upper = (n >> 32) & mask;
        int lower = n & mask;
        bitset64 upper_bs(upper);
        bitset64 lower_bs(lower);
        bitset64 result = (upper_bs << 32) | lower_bs;
        std::stringstream ss;
        ss << result;
        return ss.str();
};

int main()
{
        for(int i = 0; i < 10; ++i)
        {
                std::cout << i << ": " << to_binary(i) << "\n";
        };
        return 1;
};

这个程序的输出是:

0: 0000000000000000000000000000000000000000000000000000000000000000
1: 0000000000000000000000000000000000000000000000000000000000000001
2: 0000000000000000000000000000000000000000000000000000000000000010
3: 0000000000000000000000000000000000000000000000000000000000000011
4: 0000000000000000000000000000000000000000000000000000000000000100
5: 0000000000000000000000000000000000000000000000000000000000000101
6: 0000000000000000000000000000000000000000000000000000000000000110
7: 0000000000000000000000000000000000000000000000000000000000000111
8: 0000000000000000000000000000000000000000000000000000000000001000
9: 0000000000000000000000000000000000000000000000000000000000001001

0
如果您的目的只是将它们显示为二进制表示,则可以尝试使用 itoastd::bitset
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <bitset>

using namespace std;

int main()
{
    unsigned long long x = 1234567890;

    // c way
    char buffer[sizeof(x) * 8];
    itoa (x, buffer, 2);
    printf ("binary: %s\n",buffer);

    // c++ way
    cout << bitset<numeric_limits<unsigned long long>::digits>(x) << endl;

    return EXIT_SUCCESS;
}

2
itoa是一种非标准函数,在许多平台上不可用(我只在Windows上看到过它)。 - Evan Teran

0
void To(long long num,char *buff,int base)
{
    if(buff==NULL)      return;
    long long m=0,no=num,i=1;

    while((no/=base)>0) i++;
    buff[i]='\0';

    no=num;
    while(no>0)
    {
        m=no%base;
        no=no/base;
        buff[--i]=(m>9)?((base==16)?('A' + m - 10):m):m+48;
    }
}

0

这里有一个简单的解决方案。

#include <iostream>
using namespace std;
int main()
{
    int num=241; //Assuming 16 bit integer
    for(int i=15; i>=0; i--) cout<<((num >> i) & 1);
    cout<<endl;
    for(int i=0; i<16; i++) cout<<((num >> i) & 1);
    cout<<endl;
    return 0;
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接