在 C 中反转位并将二进制转换为十进制
Reversing bits and converting binary to decimal in C
我正在构建一个函数,给定一个整数,反转它的所有 32 位(包括符号位),将其转换为一个新整数,然后 returns 它。我快完成了,但我 运行 遇到了两个问题:
第 1 部分:
如果我给它测试(15);然后
buffer = 11110000000000000000000000000000,这确实是 15,所有位都颠倒了。
但是如果我给它测试(-15);然后
buffer = 10001111111111111111111111111111,这是不对的,应该是100010000000000000000000000000001(最后的1是符号位)。因此,对于负值,构建我的缓冲区字符串会出错。 是不是直接改成正整数,把位取反,最后的位改成1? 或者是否有更简单的方法来构建此字符串?
第 2 部分:
"answer",我返回的应该代表这些数字的整数从来都不准确。如果我给它 test(1500) answer = 185,那么它应该是 1000341504。将 32 位二进制数转换为整数的最佳方法是什么?
我的代码:
int test(int var){
printf("reversing %d:\n", var);
char buffer[32];
int i = 0;
int power = sizeof(var) * 8;
int answer = 0;
while(power > 0){
//check the lowest bit and put a 0 or 1 into the array
if((var & 1) == 1){
buffer[i] = '1';
i++;
}
else{
buffer[i] = '0';
i++;
}
//shift to the next bit
var>>= 1;
power--;
}
i++;
buffer[i] = '[=10=]';
printf("\nbuffer = %s", buffer);
//loop through the array in reverse, building the number
while(i > 0){
if(buffer[i] == '0'){
i--;
}
else{
answer += (2 ^ (32 - i)); //here is where I try to add up answer
i--;
}
}
printf("\nanswer = %d \n\n\n\n", answer);
return 0;
}
您转换的错误部分是:
answer += (2 ^ (32 - i))
2 ^ (32 - i))
是 2 XOR (32 - i)
,因为 ^
是 XOR 运算符。
我会像这样进行转换:
unsigned int answer = 0, pow=1;
for(int i = sizeof(buffer) - 1; i >= 0; --i)
{
int bit = buffer[i] - '0';
answer += bit * pow;
pow *= 2;
}
通过向后执行(从 31 到 0),您不必使用 pow
或创建
做 2 的 i 次方的函数。那会给你整数值
你的二元解释,总是积极的。如果你想要整数值
2补码二进制的:
int answer = 0;
unsigned int pow=1;
for(int i = sizeof(buffer) - 1; i > 0; --i)
{
int bit = buffer[i] - '0';
answer += bit * pow;
pow *= 2;
}
if(buffer[0] == '1')
answer |= 0x80000000; // setting last bit
或者更通用的解决方案(不关心 answer
是有符号还是无符号)
int answer = 0; // or unsigned int answer = 0;
size_t len = strlen(buffer);
for(int i = len - 1; i > 0; --i)
{
if(buffer[i] == '1')
answer |= 1 << len - 1 - i;
}
编辑
我还发现您转换为字符串时出错:
char buffer[32];
...
i++;
buffer[i] = '[=14=]';
缓冲区保持 32 char
s,每个位一个。没有余地了
那里有 0 终止字节,还有 i++
你正在溢出缓冲区,i
将是 33,所以你溢出了 2。
如果您不打算将 buffer
视为字符串(没有 strcpy
,没有 strcmp
,
没有 printf
),那么你不必存储终止 '[=30=]'
。去除那个
buffer[i] = '[=31=]';
就是这样。
但是您确实将其打印为字符串,因此您必须将 buffer
声明为
char buffer[33];
并删除 buffer[i] = '[=31=]';
.
之前的 i++
在这种情况下,您还需要将 for
循环更改为
for(i = sizeof(buffer) - 2; i >= 0; --i)
和
for(i = sizeof(buffer) - 2; i > 0; --i)
或 strlen(buffer) - 1
而不是 sizeof(buffer) - 2
(以防您执行
在另一个函数上进行转换,然后将指针传递给 buffer
.
我正在构建一个函数,给定一个整数,反转它的所有 32 位(包括符号位),将其转换为一个新整数,然后 returns 它。我快完成了,但我 运行 遇到了两个问题:
第 1 部分: 如果我给它测试(15);然后
buffer = 11110000000000000000000000000000,这确实是 15,所有位都颠倒了。
但是如果我给它测试(-15);然后
buffer = 10001111111111111111111111111111,这是不对的,应该是100010000000000000000000000000001(最后的1是符号位)。因此,对于负值,构建我的缓冲区字符串会出错。 是不是直接改成正整数,把位取反,最后的位改成1? 或者是否有更简单的方法来构建此字符串?
第 2 部分:
"answer",我返回的应该代表这些数字的整数从来都不准确。如果我给它 test(1500) answer = 185,那么它应该是 1000341504。将 32 位二进制数转换为整数的最佳方法是什么?
我的代码:
int test(int var){
printf("reversing %d:\n", var);
char buffer[32];
int i = 0;
int power = sizeof(var) * 8;
int answer = 0;
while(power > 0){
//check the lowest bit and put a 0 or 1 into the array
if((var & 1) == 1){
buffer[i] = '1';
i++;
}
else{
buffer[i] = '0';
i++;
}
//shift to the next bit
var>>= 1;
power--;
}
i++;
buffer[i] = '[=10=]';
printf("\nbuffer = %s", buffer);
//loop through the array in reverse, building the number
while(i > 0){
if(buffer[i] == '0'){
i--;
}
else{
answer += (2 ^ (32 - i)); //here is where I try to add up answer
i--;
}
}
printf("\nanswer = %d \n\n\n\n", answer);
return 0;
}
您转换的错误部分是:
answer += (2 ^ (32 - i))
2 ^ (32 - i))
是 2 XOR (32 - i)
,因为 ^
是 XOR 运算符。
我会像这样进行转换:
unsigned int answer = 0, pow=1;
for(int i = sizeof(buffer) - 1; i >= 0; --i)
{
int bit = buffer[i] - '0';
answer += bit * pow;
pow *= 2;
}
通过向后执行(从 31 到 0),您不必使用 pow
或创建
做 2 的 i 次方的函数。那会给你整数值
你的二元解释,总是积极的。如果你想要整数值
2补码二进制的:
int answer = 0;
unsigned int pow=1;
for(int i = sizeof(buffer) - 1; i > 0; --i)
{
int bit = buffer[i] - '0';
answer += bit * pow;
pow *= 2;
}
if(buffer[0] == '1')
answer |= 0x80000000; // setting last bit
或者更通用的解决方案(不关心 answer
是有符号还是无符号)
int answer = 0; // or unsigned int answer = 0;
size_t len = strlen(buffer);
for(int i = len - 1; i > 0; --i)
{
if(buffer[i] == '1')
answer |= 1 << len - 1 - i;
}
编辑
我还发现您转换为字符串时出错:
char buffer[32];
...
i++;
buffer[i] = '[=14=]';
缓冲区保持 32 char
s,每个位一个。没有余地了
那里有 0 终止字节,还有 i++
你正在溢出缓冲区,i
将是 33,所以你溢出了 2。
如果您不打算将 buffer
视为字符串(没有 strcpy
,没有 strcmp
,
没有 printf
),那么你不必存储终止 '[=30=]'
。去除那个
buffer[i] = '[=31=]';
就是这样。
但是您确实将其打印为字符串,因此您必须将 buffer
声明为
char buffer[33];
并删除 buffer[i] = '[=31=]';
.
i++
在这种情况下,您还需要将 for
循环更改为
for(i = sizeof(buffer) - 2; i >= 0; --i)
和
for(i = sizeof(buffer) - 2; i > 0; --i)
或 strlen(buffer) - 1
而不是 sizeof(buffer) - 2
(以防您执行
在另一个函数上进行转换,然后将指针传递给 buffer
.