问题描述
我正在编写一个程序,假设输入始终是有效的负十进制整数,则返回二进制补码表示(16 位)。
我的逻辑是从命令行接收输入,然后通过简单的转换将其转换为二进制并将它们添加到初始化的二进制数组中。然后,我取一个的补码(只需将 0 更改为 1,反之亦然)并将其放入 onesCom 数组中。但是,对于添加 1 部分以找到两个补码,我认为这就是问题所在,但我正在努力找到它。我正在对最低有效位执行二进制加法。
解决方法
当从一个补码转换为两个补码时,即加 1,您的循环应该从 LSB 开始,而不是从 MSB 开始。
因此,
for (j=15; j>=0; j--) { // <-- Error Here
if (onesCom[j] == 1 && carryOver == 1) {
twosCom[j] = 0;
} else if (onesCom[j] == 0 && carryOver == 1) {
twosCom[j] = 1;
carryOver = 0;
} else {
twosCom[j] = onesCom[j];
}
}
应替换为:
for (j=0; j<=15; j++) {
if (onesCom[j] == 1 && carryOver == 1) {
twosCom[j] = 0;
} else if (onesCom[j] == 0 && carryOver == 1) {
twosCom[j] = 1;
carryOver = 0;
} else {
twosCom[j] = onesCom[j];
}
}
在您的代码中,您计算一个补码,然后推导出两个补码。请注意,如果您不需要单补码,直接计算二补码会更容易,如下所示:
#include <stdlib.h>
#include <stdio.h>
int main(int argc,char *argv[]) {
int binary[16] = {0,0};
if (argc == 1) return 1;
int decimal = atoi(argv[1]);
int counter = 0;
if (decimal > -32768 && decimal < 0) {
decimal = 65536 + decimal;
while(decimal > 0) {
binary[counter] = decimal%2;
decimal = decimal/2;
counter++;
}
for (int length = 15; length >=0; length--) {
printf("%d",binary[length]);
}
printf ("\n");
}
return 0;
}
,
由于您的代码段完全模糊,我只能向您建议两种解决问题的方法:
- 第一个假设您一直在进行二进制补码运算,在这种情况下,数字加法必须用符号完成。
- 第二个假设您只解析无符号值并保留符号以在最后进行符号交换。
可能这两种方法都会导致几乎相同的效率并编译成非常相似的代码。我对其中任何一个都没有偏好。
abstract class
第二种方法是:
int decode(char *str,int base)
{
int result = 0,c,neg = FALSE;
/* skip whitespace,delete this if you don't
* want to cope with whitespace */
for (; isspace(c = *str); str++) {
continue;
}
if (*str == '-') {
neg = TRUE; /* negative */
str++; /* skip it */
}
/* the next characters might be all digits */
for (; isdigit(c = *str); str++) {
/* multiply by the base */
result *= base;
/* add positive for positives and
* subtract it for negatives */
int d = c - '0'; /* convert c to the digit value */
/* negative if number is negative */
if (neg) d = -d;
/* and add/subtract it */
result = result + d;
}
/* :) got it!! */
return result;
}
你能看出区别吗? (提示,我在循环中删除了一行并在最后更改了一行 :) )
如果您想在完整、完整且可验证的示例中运行此代码,下面有一个,只需将上述功能之一替换另一个,然后运行即可。
int decode(char *str,delete this if you don't
* want to cope with whitespace */
for (; isspace(c = *str); str++) {
continue;
}
if (*str == '-') {
neg = TRUE; /* negative */
str++; /* skip it */
}
/* the next characters might be all digits */
for (; isdigit(c = *str); str++) {
/* multiply by the base */
result *= base;
/* add positive for positives and
* subtract it for negatives */
int d = c - '0'; /* convert c to the digit value */
/* and add/subtract it */
result = result + d;
}
/* :) got it!! */
return neg ? -result : result;
}
编辑
以下代码将允许您轻松地将您的值转换为二进制:
#include <stdio.h>
#include <ctype.h>
/* these macros are for easy printing,and outputting the file,line and
* function name where the trace is being made */
#define F(_f) __FILE__":%d:%s:"_f,__LINE__,__func__
#define P(_f,...) printf(F(_f),##__VA_ARGS__)
/* I use these for portability,as <stdbool.h> is not always available */
#define FALSE (0)
#define TRUE (!FALSE)
int decode(char *str,int base)
{
/* substitute here the body of the function above you want to test */
}
int main()
{
static char *tests[] = {
"0","-1","-210","-211","-222","1","210","211","222","5400",/* add more testing cases to your wish */
NULL,};
int i,passed = 0;
for (i = 0; tests[i]; i++) {
char *test = tests[i];
int expected,actual;
P("Testing '%s' conversion\n",test);
/* expected,decoded with system routines */
if (sscanf(test,"%i",&expected) != 1) {
P("problem scanning %s\n",test);
continue;
}
/* actual,decoded with our function */
actual = decode(test,10);
char *operator = actual == expected ? "==" : "!=";
P("Test result: actual(%i) %s expected(%i)\n",actual,operator,expected);
if (actual == expected)
passed++;
}
P("passed %d/%d tests\n",passed,i);
}
最终的 #define CHK(_n) ((_n) <= sz)
char *to_binary(int p_val,char *buf,size_t sz)
{
CHK(2); /* at least two bytes of buffer space */
buf += sz; /* we start from the end,backwards to avoid having to use
* one bit masks moving all the time around */
*--buf = '\0'; /* this is the last '\0' that should end the string */
sz--; /* update buffer size */
/* we operate better with unsigned,as the
* sign doesn't get involved in shifts (we are reinterpreting
* the sign bit as a normal bit,which makes the assumption that
* integers are stored in two's complement. This is essentially
* nonportable code,but it will work in the stated assumptions. */
unsigned val = (unsigned) p_val;
/* the first below is the second char we check
* above */
do {
*--buf = val & 1 ? '1' : '0';
sz--;
val >>= 1;
} while (CHK(1) && val);
return buf; /* return what we have */
}
代码如下所示:
main()