的内容。
a0 + a1 * (2^32) + a2 * (2^32)^2 + a3 * (2^32)^3 + ...
这恰好是一个2的32次方进制系统的定义,所以忽略所有告诉你问题没有意义的人!
无论如何,您所描述的被称为进制转换。有快速的方法和简单的方法来解决此问题。快速的方法非常复杂(整本书都有专门章节介绍此主题),我不打算在此处尝试解决它们(至少因为我从未尝试使用过它们)。
一种简单的方法是首先在您的数字系统中实现两个函数,乘法和加法。(即实现BigInt add(BigInt a, BigInt b)
和BigInt mul(BigInt a, BigInt b)
)。 一旦您解决了这个问题,您会注意到一个十进制数可以表示为:
b0 + b1 * 10 + b2 * 10^2 + b3 * 10^3 + ...
也可以写成:
b0 + 10 * (b1 + 10 * (b2 + 10 * (b3 + ...
所以如果您在输入字符串中从左到右移动,您可以一次取下一个十进制数字,并使用您的 add
和 mul
函数累加到您的 BigInt
中:
BigInt a = 0;
for each digit b {
a = add(mul(a, 10), b);
}
免责声明:这种方法在计算效率上并不高,但至少可以让你开始。
注意:从十六进制转换更加简单,因为2的32次方恰好是16的倍数。因此,转换基本上就是将位串连接起来。
假设我们正在讨论一个十进制数:
a[0]*10^0 + a[1]*10^1 + a[2]*10^2 + a[3]*10^3 + ... + a[N]*10^N
每个 a[i]
都是介于0到9之间的数字。
我假设您可以解析作为输入值的字符串并查找数组 a[]
。一旦您能做到这一点,并假设您已经实现了具有 +
和 *
运算符的 BigInt
类,则您就完成了。您只需使用您的 BigInt
类的实例评估上述表达式即可。
您可以使用Horner方法相对高效地计算此表达式。
我刚刚从头脑中写下了这些内容,我敢打赌,还有更加高效的进制转换方案。
n = a_0 + a_1 * 2^32 + a_2 * 2^64 + a_3 * 2^96 + ... + a_k * 2^(32 * k).
n
,从n
中减去该幂次方的倍数,并使用差异重复该过程。BigInteger
实例? 这很容易。编写您的实现,并确保已实现+
和*
。 我完全不关心您实际上如何内部表示整数,但如果您想使用2 ^ 32进制,那么可以这样做。 然后: BigInteger Parse(string s) {
BigInteger b = new BigInteger(0);
foreach(char c in s) { b = b * 10 + (int)c - (int)'0'; }
return b;
}
我会留给你将其转换为C语言的任务。
n
无法适应寄存器时,如何执行log(n)?! - David HeffernanBigInteger
类。我对你使用的表示方法持中立态度。在这个类上实现*
和+
。现在你想解析12312398712309417234123412312037
。那么,只需这样做:BigInteger b = new BigInteger(0); foreach(char c in s) { b = b * 10 + (int)(c - '0'); }
return b;。就像我在回答中说的那样:“但是,你确定你问对了问题吗?” - jasonk = floor(log(n) / (32 * log(2)))
开始,但我不知道 n
从哪里来,也不知道如何对大整数取对数。 - David Heffernan十六进制很容易,因为2的32次方等于16的8次方,是一个精确的幂。所以,从最低有效数字开始,每次读取8个十六进制数字,将这些数字转换为32位值,那就是下一个基于2的32次方的“数字”。
十进制更加困难。正如你所说,如果它小于2的32次方,那么你只需将该值作为单个基于2的32次方的“数字”即可。否则,我能想到的最简单的方法是使用长除法算法来反复将十进制值除以2的32次方;在每个阶段,余数就是下一个基于2的32次方的“数字”。也许比我更懂数论的人可以提供更好的解决方案。
我认为这是完全合理的事情。
你正在使用32位整数数组表示一个非常大的数字(比如加密密钥)。
基于16进制表示是基于2的4次方,或者每次4位一组。如果你收到了一串基于16进制的“数字”,填充第一个整数的低4位,然后是下一个更低的4位,直到读取8个“数字”。然后进入数组中的下一个元素。
long getBase16()
{
char cCurr;
switch (cCurr = getchar())
{
case 'A':
case 'a':
return 10;
case 'B':
case 'b':
return 11;
...
default:
return cCurr - '0';
}
}
void read_input(long * plBuffer)
{
long * plDst = plBuffer;
int iPos = 32;
*(++plDst) = 0x00;
long lDigit;
while (lDigit = getBase16())
{
if (!iPos)
{
*(++plDst) = 0x00;
iPos = 32;
}
*plDst >> 4;
iPos -= 4;
*plDst |= (lDigit & 0x0F) << 28
}
}
还有一些修复工作要做,比如以 iPos 移动 *plDst 结尾,并跟踪您的数组中整数的数量。
还需要一些从十进制转换的工作。
但这已足以让您开始了。
a0 + a1*(2^32) + a2*(2^32)^2 + ...
的东西,因此他需要一个从十进制到基于2^32的转换器。我们恰好称之为“大整数”数据类型,但这并不否定OP的问题。 - Oliver Charlesworth