如何正确添加/减去128位数字(如两个u_int64_t)
我在C中工作,需要添加和减去64位数字和128位数字。 结果将保存在128位数字中。 我使用整数数组来存储128位数的上半部和下半部(即u_int64_t bigNum[2]
,其中bigNum[0]
是最不重要的)。
任何人都可以帮助添加和减法函数,可以接受bigNum并添加/减去u_int64_t
吗?
我在网上看到了很多不正确的例子,所以请考虑一下:
bigNum[0] = 0; bigNum[1] = 1; subtract(&bigNum, 1);
此时bigNum[0]
应该设置所有位,而bigNum[1]
应该没有设置位。
在1年级或2年级,你应该学会如何将1和10的加法分解成几部分,将它分成几个单位和单位的多个单独添加。 处理大数时,相同的原理可以应用于计算任意大数的算术运算,通过实现你的单位现在是2 ^位的单位,你的“十”是2 ^位更大,依此类推。
这适用于减法:
typedef u_int64_t bigNum[2]; void subtract(bigNum *a, u_int64_t b) { const u_int64_t borrow = b > a[1]; a[1] -= b; a[0] -= borrow; }
增加非常相似。 当然,上面的内容也可以用明确的测试来表达,但我发现总是借用它会更清晰。 优化留作练习。
对于等于{ 0, 1 }
的bigNum
,减去2会使它等于{ ~0UL, ~0UL }
,这是表示-1的正确位模式。 这里,假设UL将整数提升到64位,当然这取决于编译器。
对于您减去的值小于或等于bignum[0]
您不必触摸bignum[1]
。
如果不是,你可以从bignum[0]
减去它,无论如何。 此操作将环绕,但这是您需要的行为。 此外,你必须从bignum[1]
取代1。
大多数编译器本质上支持__int128类型。
尝试一下,你可能会很幸运。
在汇编中,在任意长整数中进行加法/减法非常容易,因为有一个进位标志和带有标志指令的add / sub。
在C中,无法访问此进位标志,因此您必须自己计算该标志。 但这需要很多位操作。 您可以在此处使用更简单的解决方案