我有一些我编写的代码会成功返回二进制数字。例如,使用输入101运行下面的代码将返回5.但是,当我在MSB的左侧添加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后立即看到,将值5存储在rem1中,而不是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?
我不确定发生了什么,感谢任何帮助!
答案 0 :(得分:4)
101
被解析为十进制(基数为10)的数字,因此您可以获得预期的输出。
0101
被解析为八进制(基数为8)。这里的前导零就像前导0x
前缀一样,表示十六进制(基数为16)的数字,除了没有x
它的基数为8而不是基数为16. †功能
101 8 = 8 2 + 8 0 = 64 + 1 = 65
65%10 = 5
65/10 = 6
6%10 = 7
5 * 2 + 7 = 17
如果我是您,我会在您分配到assert(rem1 == 0 || rem1 == 1)
后立即在您的循环中添加rem1
作为完整性检查。如果你得到一个大于一或小于零的余数,那么显然有些不对劲。
正如rbaleksandar在上面的评论中指出的,避免此问题的最简单方法可能是将输入存储为c-string(char[]
)而不是使用整数文字。这也很好,因为您可以迭代字符来计算值,而不是执行%
和/
操作。
或者,您可以对所有输入使用十六进制文字(例如0x101
或0x0101
),并将数学更改为使用基数16而不是基数10.这具有额外的优势:基数10除法和余数函数可以由编译器优化为更便宜的位移和位掩码操作,因为16是2的幂。(例如,0x101 % 16
==&gt; 0x101 & 15
,并且0x101 / 16
==&gt; 0x101 >> 4
)。
†欲了解更多信息 见http://en.cppreference.com/w/cpp/language/integer_literal
答案 1 :(得分:0)
0101是八进制数,其值为17.