将二进制数转换为十进制数的代码

3
我有一段代码,可以成功地返回二进制数。例如,使用下面的代码并输入101将会返回5。然而,当我在最高有效位左侧添加0比特时,问题就出现了,因此不改变该值。当我将0101输入到系统中时,我应该再次期望返回5,但实际上它返回17。
这是我的代码:
int dec1 = 0, rem1=0, num1, base1 = 1;

int a = 101;
while (a > 0){

    rem1 = a % 10;
    dec1 = dec1 + (rem1 * base1);
    base1 = base1 * 2;
    a = a / 10;
}
cout << dec1 << endl;

这个输出是5。正确。

然而,当'a'被改为0101时,输出变成了17。我认为我的错误与对取模运算符的误解有关。

101%10 = 1 对吗?编译器通常会以相同的方式读取0101%10吗?

我在代码中添加了一个cout语句,以查看在计算0101%10的值之后rem1中存储了什么值。

int dec1 = 0, rem1=0, num1, base1 = 1;

int a = 101;
while (a > 0){

    rem1 = a % 10;
    cout << rem1 << endl;
    dec1 = dec1 + (rem1 * base1);
    base1 = base1 * 2;
    a = a / 10;
}
cout << dec1 << endl;

从这里,我能够看到在计算0101%10之后,rem1存储了5而不是1的值。
在MSB前面添加0是否告诉编译器“嘿,这个数字是二进制的?”因为如果编译器读取的是5%10而不是0101%10,则我猜错误是有道理的。
经过测试我的理论,我将'a'更改为1000,输出结果为8,这是正确的。
将'a'更改为01000会得到24的结果。 rem1 = 01000%10应该是0,然而rem1存储了2。 01000二进制= 8十进制。 8%10 = 8?而不是2?
我不确定发生了什么,任何帮助都将不胜感激!

2
我认为你存储二进制数的方式是错误的。你应该使用二进制字符串代替。你可能会问为什么这样做?嗯,因为如果按照你现在的方式存储1和0,很快就会达到整数的限制。目前,你的int a101以十进制形式存储,即"一百零一"。 - rbaleksandar
为什么不使用位移运算符来解决这个问题呢?如果您想让我发布一个解决方案,我可以提供,但这听起来像是一道作业题,我不想泄露答案。 - PentiumPro200
2个回答

4

101被解析为十进制(base 10)数字,因此您可以得到预期的输出。

0101由于前导零被解析为八进制(base 8)数字。这里的前导零的作用就像表示16进制(base 16)数字的前导0x前缀一样,但是没有x,它是8进制而不是16进制。

1018 = 82 + 80 = 64 + 1 = 65

65 % 10 = 5

65 / 10 = 6

6 % 10 = 7

5 * 2 + 7 = 17

如果我是您,在循环之后,我会添加一个assert(rem1 == 0 || rem1 == 1)来进行检查。如果您得到大于一或小于零的余数,则显然有问题。

正如rbaleksandar在他上面的评论中指出的那样,避免此问题的最简单方法可能是将输入存储为c字符串(char []),而不是使用整数字面值。这样做也很好,因为您可以只迭代字符来计算该值,而无需进行%/操作。

或者,您可以对所有输入使用十六进制文字(例如0x1010x0101),并更改您的数学以使用16进制而不是10进制。这样做的附加优势是,由于16是2的幂,因此可以将基于10的除法和余数函数优化为更便宜的位移和位掩码操作。 (例如,0x101%16 ==> 0x101&150x101/16 ==>0x101>> 4)。


有关更多信息,请参见http://en.cppreference.com/w/cpp/language/integer_literal


0

0101是八进制数,其值为17。


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