我有字符串 s 的指纹, f(s) = (S[1]r^m-1) xor (S[2]r^m-2) xor....(xor S[n]r^0 )) mod (2^32) 让 s 只包含 a 和 b (分别为 0,1)。
如果它是加法而不是异或,那将很容易。我们可以使用以下规则来解决它:(a + b)mod m = ((a mod m) + (b mod m)) mod m,但这里不是这样。因此,任何想法都请记住,我无法计算例如 r^m-1,因为我可能面临整数溢出。
我有字符串 s 的指纹, f(s) = (S[1]r^m-1) xor (S[2]r^m-2) xor....(xor S[n]r^0 )) mod (2^32) 让 s 只包含 a 和 b (分别为 0,1)。
如果它是加法而不是异或,那将很容易。我们可以使用以下规则来解决它:(a + b)mod m = ((a mod m) + (b mod m)) mod m,但这里不是这样。因此,任何想法都请记住,我无法计算例如 r^m-1,因为我可能面临整数溢出。
如果担心溢出,我建议使用BigInteger
它不会溢出假设你有足够的内存:
文档 :
算术运算的语义完全模仿 Java 的整数算术运算符,如 Java 语言规范中所定义。例如,除以零会引发 ArithmeticException,而负数除以正数会产生负数(或零)余数。规范中关于溢出的所有细节都被忽略了,因为 BigInteger 被制作得尽可能大以适应操作的结果。
BigInteger 并不是真正的类型。这是一堂课。它是一个包装类,旨在为您提供与 int 相同的功能,但允许您使用任意大小的数字而无需担心溢出。
类型确实会溢出,因为它们只是内存的几个字节(确切数量取决于类型),一旦少量内存溢出,数字也会溢出。
没有类“溢出”,除非它是专门设计的(或者如果你用完了资源)。一个类被定义为它包含的所有内容都有足够的内存,这主要是对其他类或其他数据结构的引用。
溢出不是问题,因为:
mod 2^32
屏蔽高位的最终动作只需使用 along
来保存您的结果(64 位,因此第 31 位不会导致符号问题)。
等等……如果 m 只是 S 的长度,那就简单多了:
int re = 1;
int sig = 0;
for (int i=m-1; i>=0; --m) {
if (s[i] != 0)
sig ^= re;
re = (re*r) & 0xffffffff;
}
这对我来说似乎太简单了。你确定你的表达正确吗?
(我原来的回答:
如果您还没有整数指数函数,请从整数指数函数开始:
/**
* Return x^e, mod 2^32
*/
unsigned int
iExp(unsigned int x, unsigned int e)
{
unsigned int rval = 1;
while (e > 0) {
if ((e & 1) != 0)
rval *= x;
x *= x;
e >>= 1;
}
return rval & 0xffffffff;
}
如果 S 是一个 0 或 1 值的数组,那么对于子表达式的其余部分,它实际上是一个“使用”/“不使用”标志:
// I've taken the liberty of indexing S starting at 0 instead of 1
// compute f(s) = (S[0]r^m-1) xor (S[1]r^m-2) xor....(xor S[m-1]r^0)) mod (2^32)
int rval = 0;
for (x : S) {
--m;
if (x != 0)
rval ^= iExpr(r, m);
}
我还没有测试过这个(我没有任何测试向量),但这应该可以。
JavaBigInteger
类不支持提升到类型的指数BigInteger
。您可以做的是实现一种算法来自己计算幂,使用Exponentiation by Squaring。这些通常以递归算法的形式出现,该算法将计算您的功率,而实际上不会将数字提高到超过2
(因此平方)的指数。
然而, JavaBigInteger
类确实处理了溢出问题。