我正在尝试编写一个 C 程序将十进制转换为二进制。以下代码可以将十进制整数转换为二进制。
#include <stdio.h>
#include <math.h>
int main()
{
long int n;
printf("Enter a Positive Integer (decimal): ");
scanf("%d", &n);
long int temp = n;
int r; long long int bin = 0;
int p = 0;
while(temp > 0)
{
r = temp % 2; printf("%d\t", r); // printing r value for debugging
bin += (r * pow(10, p));
temp /= 2;
p++;
}
printf("\n%lld", bin);
return 0;
}
我已经测试了多个随机值的代码,并获得了大多数随机值的预期输出,除了两个特定值“99999”和“419862”。对于“99999”,预期输出是“11000011010011111”,但我得到“11000011010011112”。对于“419862”,预期输出是“1100110100000010110”,但我得到“1100110100000010112”。除最后一个数字外的所有数字均正确匹配。获得“2”而不是“1”和“0”。为了调试代码,我在
printf("%d\t", r);
语句之后立即添加了 r = temp % 2;
。如此打印的r值给出了正确的预期输出。这是输出:
对于“99999”,输出为
Enter a Positive Integer (decimal): 99999
1 1 1 1 1 0 0 1 0 1 1 0 0 0 0 1 1
11000011010011112
对于“419862”,输出是
Enter a Positive Integer (decimal): 419862
0 1 1 0 1 0 0 0 0 0 0 1 0 1 1 0 0 1 1
1100110100000010112
注意:单独打印的r值是相反的。
为什么第一个余数分别使用
printf("%d\t", r);
'1' 和 '0' 打印
(对于'99999'和'419862'),但是复合赋值得到的bin值的个位数不一样?
bin += (r * pow(10, p));
的意思是bin = bin + (r * pow(10, p));
。 (N1570 6.5.16.2 复合赋值)
根据通常的算术转换(N1570 6.3.1.8),乘法
*
和加法+
当其中一个操作数是double
(而另一个是实数类型而不是时)将产生
double
结果long double
)。
pow
函数 (N1570 7.12.7.4) 返回 double
,因此 r * pow(10, p)
具有类型 double
,因此 bin + (r * pow(10, p))
也具有 double
类型。
通常使用 64 位 IEEE754 格式来表示
double
。据说这种格式的精度大约是15位小数。
在输入
99999
的最后一次迭代中,添加值 1000011010011111
和 10000000000000000
。它们分别有 16 和 17 位数字。
这超出了 15 位数字的限制,出现精度错误的机会会很高。
总之,您会遇到舍入错误,因为您使用了浮点值,而应使用具有多位数字的整数。
例如,在这种情况下可以通过这种方式消除使用
pow
(使用乘数变量mult
并增量乘以10
,而不是在每次迭代中计算功率):
long long int mult = 1;
while(temp > 0)
{
r = temp % 2; printf("%d\t", r); // printing r value for debugging
bin += (r * mult);
temp /= 2;
mult *= 10;
}