我有以下功能。我是从两个网站上得到的,并尝试将其改编成我自己的网站,但效果并不好。
当我测试export LC_ALL=en_US.utf-8
export LANG=en_US.utf-8
或者将其作为数字unsigned long int max - 2
进行测试时,它将以下代码置于无限循环中,其中4294967293
将继续返回相同的值。
我对分解算法非常陌生,并逐步帮助我获得无限循环的原因。
以下代码只是我的“rho”功能。我有另一个名为ys
的函数,它与其他每个gdc
递归函数相同。
gdc
我调整了以下代码的示例:
我已经完成,因为Amd建议并整理我的代码并将重复的行移动到辅助函数中。但是我仍然在底部附近的unsigned long int rho(unsigned long int n)
{
if (n == 1) return n;
if (n % 2 == 0) return 2;
unsigned long int y = rand() % n;
unsigned long int x;
unsigned long long int ys = y;
unsigned long int c;
do
c = rand() % n;
while (c == 0 || c == n - 2);
unsigned long int m = 1000;
unsigned long int d = 1;
unsigned long int q = 1;
unsigned long int r = 1;
while (d == 1)
{
x = y;
for (int i = 0; i < r; i++)
{
y = y * y % n;
y += c;
if (y < c)
y += (std::numeric_limits<unsigned long>::max() - n) + 1;
y %= n;
}
int j = 0;
while (j < r && d == 1)
{
ys = y;
for (int i = 0; i < m && i < (r-j); i++)
{
y = y * y % n;
y += c;
if (y < c)
y += (std::numeric_limits<unsigned long>::max() - n) + 1;
y %= n;
q *= ((x>y) ? x - y : y - x) % n;
}
d = gcd(q, n);
j += m;
}
r *= 2;
}
if (d == n)
{
do
{
ys = ys * ys % n;
std::cout << ys << std::endl;
ys += c;
if (ys < c)
ys += (std::numeric_limits<unsigned long>::max() - n) + 1;
ys %= n;
d = gcd( ((x>ys) ? x - ys : ys - x) , n);
} while (d == 1);
}
return d;
}
部分获得无限循环。出于某种原因,d==n
最终基本上返回了之前返回的相同内容,因此它会循环显示一系列值。
f(ys)
答案 0 :(得分:1)
应始终终止。当你到达算法中的那一点时,x
将在周期内(从y
开始x
并开始使用Brent&#39来检测周期; s循环检测)。价值ys
从y
开始,从x
开始,因此它也将在整个周期内继续并最终再次与x
见面(参见Floyd或Tortoise和Hare周期)检测)。此时您将拥有gcd(ys,x)==x
,最终循环将终止。
发布的实施中有几个错误,我认为可能导致问题:
x = y;
for (int i = 0; i < r; i++) // should be strictly less than
...
ys = y;
for (int i = 0; i < min(m, r-j); i++) // again, strictly less than
{
y = f(y, c, n);
q = (q*abs(x,y)) % n; // needs "mod" operator AFTER multiplication
}
...
您还可以使用
替换c
的初始化
uint64_t c = (rand() % (n-3))+1
如果你想要一个[1,n-3]范围内的数字。
这是Richard P. Brent的原始论文:An Improved Monte-Carlo Factorization Algorithm
答案 1 :(得分:0)
修改强>
这对我有用,而不是陷入无限循环:
#include<iostream>
#include<stdint.h>
#define min(a,b) (a<b?a:b)
#define abs(x,y) (x > y? x - y : y - x)
uint64_t gcd(uint64_t m, uint64_t n) {
while (true) {
int r = m % n;
if (r == 0) {
return n;
}
m = n;
n = r;
}
}
uint64_t f(uint64_t y, uint64_t c, uint64_t n) {
y = (y * y) % n;
y += c;
if (y < c)
y += (std::numeric_limits<uint32_t>::max() - n) + 1;
y %= n;
return y;
}
uint64_t rho(uint64_t n)
{
if (n == 1) return n;
if (n % 2 == 0) return 2;
uint64_t y = rand() % n;
uint64_t x;
uint64_t ys = y;
uint64_t c;
do c = rand() % n; while (c == 0 || c == n - 2);
uint64_t m = 1000;
uint64_t d = 1;
uint64_t q = 1;
uint64_t r = 1;
do
{
x = y;
for (int i = 0; i <= r; i++)
y = f(y, c, n);
int j = 0;
do
{
ys = y;
for (int i = 0; i <= min(m, r - j); i++)
{
y = f(y, c, n);
q *= (abs(x, y) % n);
}
d = gcd(q, n);
j += m;
} while (j < r && d == 1);
r *= 2;
} while (d == 1);
if (d == n)
{
do
{
ys = f(ys, c, n);
d = gcd(abs(x, ys), n);
} while (d == 1);
}
return d;
}
int main() {
std::cout << rho(std::numeric_limits<uint32_t>::max() - 2) << "\n"; //9241
}
<强>旧强>
根据改进的蒙特卡罗分解算法:http://wwwmaths.anu.edu.au/~brent/pd/rpb051i.pdf
PP:182-183
错误:ys = x * x%n;
正确:ys = ys * ys%n; // ys = f(ys)
请使用来自stdint.h的uint32_t或uint64_t ...以获得良好和干净的编码风格:
#include<iostream>
#include<stdint.h>
int gcd(int m, int n) {
while (true) {
int r = m % n;
if (r == 0) {
return n;
}
m = n;
n = r;
}
}
#define min(a,b) (a<b?a:b)
#define abs(x,y) (x > y? x - y : y - x)
uint32_t f(uint32_t y, uint32_t c, uint32_t n) {
y = (y * y) % n;
y += c;
if (y < c)
y += (std::numeric_limits<uint32_t>::max() - n) + 1;
y %= n;
return y;
}
//http://wwwmaths.anu.edu.au/~brent/pd/rpb051i.pdf
//pp:182-183
uint32_t rho(uint32_t n) {
if (n == 1) return n;
if (n % 2 == 0) return 2;
uint32_t y = rand() % n; // y = x0
uint32_t x;
uint64_t ys = y;
uint32_t c;
do { c = rand() % n; } while (c == 0 || c == n - 2);
uint32_t m = 1000;
uint32_t d = 1;
uint32_t q = 1;
uint32_t r = 1;
do
{
x = y;
for (int i = 1; i <= r; i++) y = f(y, c, n);
int j = 0;
do
{
ys = y;
for (int i = 1; i <= min(m, r - j); i++)
{
y = f(y, c, n);
q = q * abs(x, y) % n;
}
d = gcd(q, n);
j += m;
} while (j < r && d == 1);
r *= 2;
} while (d == 1);
if (d == n)
{
do
{
ys = f(ys, c, n);//not: ys = f(x,c,n);
d = gcd(abs(x, ys), n);
} while (d == 1);
}
return d;
}