看代码吧,没有太多要说的
cs
using System.Numerics;
using System.Security.Cryptography;
namespace ShorAlgorithm;
class Program
{
/*********************************************************************
* shor.cc -- Use Shor's Algorithm
* to factor a large BigInteger
* ChangeLog:
* 970225 -- Created by Paul Herman <a540pau@pslc.ucla.edu>
**********************************************************************/
static BigInteger GenerateRandomOddBigInteger(int count = 8)
{
if (count <= 0) throw new ArgumentException(null, nameof(count));
// 创建一个RandomNumberGenerator实例
using var generator = RandomNumberGenerator.Create();
// 生成一个足够长的字节数组,例如16字节(128位)
var randomBytes = new byte[count]; // 可以根据需要增加字节数以生成更大的数
generator.GetBytes(randomBytes);
randomBytes[0] |= 1; // 确保生成的数是奇数,以增加找到因子的概率
// 将字节数组转换为BigInteger
// 注意:这里使用了BigEndianBitConverter,因为BigInteger期望高位在前(大端格式)
randomBytes[^1] &= 0x7f; // 确保生成的数是正数
return new (randomBytes);
}
/********************************************************************
/* Period: This computes the size of the group generated by a mod n
/* i.e. |<a>|
/********************************************************************/
static long GetCycle(BigInteger a, BigInteger n)
{
var count = 1L;
Parallel.For(1L, long.MaxValue, (i, state) =>
{
if (BigInteger.ModPow(a, i, n) == BigInteger.One)
{
count = i;
state.Stop();
}
});
return count;
}
/************************************************************************************
/* ShorFactor: Finds a factor of n by looking at the group generated
/* by <a> mod n. Let t = |<a>|/2 . Check to see if
/* t +/- 1 and n have a common factor. If not, try another a
/************************************************************************************/
static BigInteger ShorFactor(BigInteger n, BigInteger a, long retries = 4096, bool use_cycle = false)
{
BigInteger t1, t2, f1, f2, r;
int j;
a = a.IsZero ? GenerateRandomOddBigInteger(n.GetByteCount()) : a;
while (true)
{
j = 2;
//我在这里改为随机化
r = use_cycle ? GetCycle(a, n) : BigInteger.ModPow(a, j, n);
for (; ; j++)
{
//随机数a是n的因子
f1 = BigInteger.GreatestCommonDivisor(a, n);
if (f1 == n) goto tail;
if (f1 != BigInteger.One) return f1;
//t1和t2分别是a^((a^j mod n)/2) mod n的+1和-1
t1 = BigInteger.ModPow(a, (r >> 1), n);
t1 += 1;
t2 = t1 - 2;
//t1=(a^(r/2) mod n) + 1
//t2=(a^(r/2) mod n) - 1
//测试t1
f1 = BigInteger.GreatestCommonDivisor(t1, n);
if (f1 != BigInteger.One && f1 != n)
return f1;
//测试t2
f2 = BigInteger.GreatestCommonDivisor(t2, n);
if (f2 != BigInteger.One && f2 != n)
return f2;
//如果t1和t2都没有找到因子,那么就换一个a继续试s
a += 1;
if (--retries == 0)
return n;
//计算a^j mod n,求r的下一个数值
r = BigInteger.ModPow(a, j, n);
//如果r为负数,说明a^j mod n的结果是负数,这不应该发生,因为模运算的结果应该在0到n-1之间
if (r < 0) goto tail;
}
tail:
a = GenerateRandomOddBigInteger(n.GetByteCount());
}
}
public static bool IsPrime(BigInteger number)
{
// 小于等于1的数不是质数
if (number <= 1)
return false;
// 2 是质数
if (number == 2)
return true;
// 偶数(除了2)不是质数
if (number.IsEven)
return false;
// 使用试除法检查从3到√n的所有奇数
BigInteger sqrt = Sqrt(number);
for (BigInteger i = 3; i <= sqrt; i += 2)
{
if (number % i == 0)
return false;
}
return true;
}
// 计算 BigInteger 的平方根
private static BigInteger Sqrt(BigInteger number)
{
if (number == 0)
return 0;
BigInteger x = number;
BigInteger y = (x + 1) / 2;
while (y < x)
{
x = y;
y = (x + number / x) / 2;
}
return x;
}
static BigInteger default_value = 70191551;
static int Main(string[] args)
{
default_value = GenerateRandomOddBigInteger(32);
var n = args.Length > 0
? BigInteger.TryParse(args[0], out var v)
? v : default_value
: default_value
;
var u = n;
List<BigInteger> factors = [];
Console.WriteLine($"Factoring n = {n}:");
var i = 1;
var retries = n.GetByteCount() * 4096;
while (n != BigInteger.One)
{
var factor = ShorFactor(n, BigInteger.Zero, retries);
Console.WriteLine($"Found factor{i} = {factor}, IsPrime={IsPrime(factor)}");
n /= factor;
i++;
factors.Add(factor);
}
Console.WriteLine("Factorization complete.");
var s = factors.Aggregate((a, b) => a * b);
if (s == u)
{
Console.WriteLine("Verification: OK.");
}
else
{
Console.WriteLine("Verification: Fail.");
}
return 0;
}
}