问题就在这里:
#define abs(x) (x>0)?(x):(-x)
你的abs
宏中缺少一些括号。试试这样:
#define abs(x) ((x)>0 ? (x) : -(x))
考虑使用 abs(x-xx)
时在 x-xx <= 0
的情况下会发生什么。
此外,为什么你的 gcd 函数返回 int 而不是 BigInteger?
你还应该注意,假设 unsigned long long 是一个 64 位整数类型,这段代码对于 N
大于 2**32
的情况将无法正确工作:如果 x
(或 xx
)大于或等于 2**32
,那么 x*x
将在模 2**64
的情况下溢出,从而给出 x*x % N
的错误值。
我注意到一个区别:Java代码将c
和x
赋值为new BigInteger(N.bitLength(), random)
,而C++代码使用rand() % N
,这是一个较小的随机范围。对于值9999,二进制表示为10011100001111,因此Java代码将使c
和x
的最大值为16383。
BigInteger(N.bitLength(), random)
将生成0到2^14-1之间的整数,而rand() % N
将生成0到9998之间的整数。这不是代码中的关键错误,但它也不是Java版本的准确翻译。 - Adrian Cox#include <stdlib.h>
#include <stdint.h>
typedef uint_fast64_t num ;
static inline num mul_mod(num a, num b, const num mod) {
// Return (a * b) % mod, avoiding overflow errors while doing modular multiplication.
num res = 0, tmp;
for (b %= mod; a; a & 1 ? b >= mod - res ? res -= mod : 0, res += b : 0, a >>= 1, (tmp = b) >= mod - b ? tmp -= mod : 0, b += tmp);
return res % mod;
}
static inline num square_root(num n) {
// Return the number that was multiplied by itself to reach N.
num a = 0, b, c;
for (b = 1ULL << 62; b; c = a + b, n -= c &= -(n >= c), a = (a >> 1) | (c & b), b >>= 2);
// Variable n contains the remainder.
return a;
}
有一个必需的质数检查器:
static int is_prime(const num n, size_t iterations) {
// Perform a Miller-Rabin (strong probable prime) test.
num a = 0, b, c, d, e, f; int h, i;
if ((n == 1) == (n & 1)) return n == 2;
for (b = c = n - 1, h = 0; !(b & 1); b >>= 1, ++h);
for (; iterations--;) {
for (size_t g = 0; g < sizeof(a); ((char*)&a)[g++] = rand()); // random input.
do for (d = e = 1 + a % c, f = n; (d %= f) && (f %= d););
while (d > 1 && f > 1);
for (d = f = 1; f <= b; f <<= 1);
for (; f >>= 1; d = mul_mod(d, d, n), f & b && (d = mul_mod(e, d, n)));
if (d == 1) continue;
for (i = h; i-- && d != c; d = mul_mod(d, d, n));
if (d != c) return 0;
}
return 1;
}
有两个因数分解函数:
static inline num factor_worker_2(const num n, size_t limit) {
// Perform a Pollard's Rho probabilistic test.
size_t a = -1, b = 2;
num c, d = 1 + rand(), e = 1, f = 1;
for (c = d %= n; f == 1 && --limit; d = c, b <<= 1, a = -1) {
for (; f |= e, f == 1 && ++a != b;) {
c = mul_mod(c, c, n);
for (++c, c *= c != n, e = n, f = c > d ? c - d : d - c; (f %= e) && (e %= f););
}
}
return f;
}
static inline num factor_worker_1(const num n) {
// Perform a trial divisions test on N.
static const num list[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 1};
size_t i;
for (i = -1; n % list[++i];);
return list[i];
}
有一个因式分解的管理器:
num factor(const num n) {
// Basic factorization manager, detect primes, perfect squares, execute workers.
num res;
switch (n) {
case 0: case 1: case 2: case 3:
res = 1; break;
default:
res = factor_worker_1(n);
if (res == 1 && !is_prime(n, 20)) {
res = square_root(n);
if (res * res != n)
for(;res = factor_worker_2(n, -1), res == 1 || res == n;);
}
}
return res;
}
有一个 主函数 :
#include <assert.h>
#include <stdio.h>
int main(void) {
num N;
N = 951818131364430049;
printf("factor is %zu\n", factor(N));
}
为了尝试它:
// You can put it into a main.c file then compile + execute :
// gcc -O3 -std=c99 -Wall -pedantic main.c ; ./a.out ;
这里是源代码,获取更多信息,请谢谢。