我正在C中构建一个可以获得2
幂的程序。用户输入n
的值,程序将计算2^n
。
这是code。
当我输入100
我得到的是什么:
1,267,650,600,228,229,400,000,000,000,000
我应该得到什么
1,267,650,600,228,229,401,496,703,205,376
它必须完全用ANSI C编码。有关如何提高精度的任何想法? N
的最大值必须为256
(256位,我想,这意味着最大输出应为2^256
)。
我在这里缺少的是精确度,我不知道如何解决这个问题。有什么想法吗?
答案 0 :(得分:4)
如果你从一开始就在10号基地工作,我认为这是最简单的。这是因为虽然二进制计算2的幂是微不足道的,但转换回基数10要困难得多。
如果您有一个基数为10的数组 1 ,您只需要实现基数10加法,并且可以乘以2(通过将数字加到自身)。在循环中执行n
次,即可获得答案。
如果你想支持更高的指数,你也可以考虑通过平方来实现取幂,但这更难,因为你需要通用乘法,而不仅仅是2。
1 提示:如果以相反的顺序存储数字,会更方便。
答案 1 :(得分:2)
这是我对hammar's approach.的快速而又脏的实现,将十进制数存储为C字符串,其中数字的顺序相反。
void doubleDecimal(char * decimal)
{
char buffer[256] = "";
char c;
unsigned char d, carry = 0;
int i = 0;
while (c = decimal[i])
{
d = 2 * (c - '0') + carry;
buffer[i] = (d % 10) + '0';
carry = d / 10;
i++;
}
if (carry > 0)
buffer[i++] = (carry % 10) + '0';
buffer[i] = '\0';
strncpy(decimal, buffer, 256);
}
void reverse(char * str)
{
int i = 0;
int j = strlen(str) - 1;
while (j > i)
{
char tmp = str[i];
str[i] = str[j];
str[j] = tmp;
i++;
j--;
}
}
int main(void)
{
char decimal[256] = "1";
int i;
for (i = 0; i < 100; i++)
doubleDecimal(decimal);
reverse(decimal);
printf("%s", decimal);
return 0;
}
输出:
1267650600228229401496703205376
答案 2 :(得分:1)
double是(可能)64位值。您不能以64位存储256位精度。你得到一个接近的数字的原因是因为浮点数以不同的精度存储 - 不是所有的序号都可以表示,但你可以代表非常大的数字。在这种情况下相当无用。 你想要的是使用任意精度库,或者,因为这可能是家庭作业,你应该自己编写。
答案 3 :(得分:1)
使用64位IEEE 754的典型double
具有大约51位精度,IIRC。
最有可能支持高达256的指数超过该精度,以及long double
或long long
的精度,因此您必须自己做事。
作为家庭作业,那么,
答案 4 :(得分:0)
您需要考虑的一些事情来解决这个问题:
答案 5 :(得分:0)
您不能以64位存储256位精度。要获得要关闭的数字的原因是因为浮点数以不同的精度存储。可以表示所有序列号,但您可以表示非常大的数字。在这种情况下相当无用。
答案 6 :(得分:0)
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//constants
#define MAX_DIGITS 1000
//big integer number struct
struct bigint {
char Digits[MAX_DIGITS];
};
//assign a value
void assign(struct bigint* Number,int Value) {
if (Value!=1) {
printf("Can not assign value other than 1\n");
exit(0);
}
memset(Number,0,sizeof(bigint));
Number->Digits[0] = Value;
}
//multiply the big integer number with value
void multiply(struct bigint* Number,int Value) {
int Digit,New_Digit;
int Carry = 0;
for (int Index=0; Index<MAX_DIGITS; Index++) {
Digit = Number->Digits[Index];
New_Digit = Digit*Value%10;
if (New_Digit+Carry<10) {
New_Digit = New_Digit+Carry;
Carry = Digit*Value/10;
}
else {
New_Digit = (New_Digit+Carry)%10;
Carry = (Digit*Value/10)+1;
}
//set the new digit
Number->Digits[Index] = New_Digit;
}//for loop
}
//print out the value of big integer type
void print(struct bigint* Number) {
int Index = MAX_DIGITS-1;
while (Number->Digits[Index]==0 && Index>=0)
Index--;
//the big integer value is zero
if (Index==-1) {
printf("0");
return;
}
while (Index>=0) {
printf("%u",Number->Digits[Index]);
Index--;
}
}
//main programme entry point
int main(int Argc,char** Args) {
int Power = 100;
struct bigint Number;
//assign the initial value
assign(&Number,1);
//do the multiplication
for (int Index=0; Index<Power; Index++)
multiply(&Number,2);
//print result
print(&Number);
getch();
}
//END-OF-FILE