这是我对费马小定理的实现。有谁知道为什么它不起作用?
以下是我遵循的规则:
mycode的:
int low = 2;
int high = n -1;
Random rand = new Random();
//Pick any integer a between 2 and n-1.
Double a = (double) (rand.nextInt(high-low) + low);
//compute:a^n = a mod n
Double val = Math.pow(a,n) % n;
//check whether a^n = a mod n
if(a.equals(val)){
return "True";
}else{
return "False";
}
这是一个小于100000的素数列表。每当我输入任何这些数字,而不是得到'真',我得到'假'。
这就是我认为代码无效的原因。
答案 0 :(得分:1)
在java中,double只有大约15到17位数的有限精度。这意味着虽然您可以计算Math.pow(a,n)
的值,但对于非常大的数字,您无法保证一旦值超过15位,您将获得准确的结果。
使用较大的a或n值时,您的计算将超出该限制。例如
Math.pow(3, 67)
的值为9.270946314789783e31
,这意味着最后3位之后的任何数字都会丢失。因此,在应用模运算后,您无法保证获得正确的结果(example)。
这意味着您的代码实际上并未测试您的想法。这是浮点数工作方式所固有的,您必须更改保持值以解决此问题的方式。你可以使用long
,但是你会遇到溢出问题(长期不能保持大于2^64 - 1
的值,所以再次,3^67
你会遇到另一个问题。< / p>
一种解决方案是使用一个用于保存任意大数字的类,例如BigInteger
的{{1}}。
答案 1 :(得分:1)
正如其他人所说,取力会迅速溢出。例如,如果你选择数字n来测试小到30的素数,并且随机数a是20,20 ^ 30 =大约10 ^ 39这是&gt;&gt; 2 ^ 90。 (我拿了10 ^ 39的ln。)
您想使用BigInteger,它甚至拥有您想要的确切方法:
public BigInteger modPow(BigInteger exponent, BigInteger m)
“返回一个BigInteger,其值为(this ^ exponent mod m)”
另外,我认为测试2和n-1之间的单个随机数不会“证明”任何东西。你必须循环遍历2和n-1之间的所有整数。
答案 2 :(得分:1)
@evthim即使您已经使用BigInteger类的modPow函数,也无法获得正确选择范围内的所有素数。为了进一步阐明问题,您将获得该范围内的所有质数,但是有些数字不是质数。如果您使用BigInteger类重新排列此代码。当您尝试所有64位数字时,一些非质数也会写入。这些数字如下;
341、561、645、1105、1387、1729、1905、2047、2465、2701、2821、3277、4033、4369、4371、4681、5461、6601,7957、8321、8481、8911、10261、10585 ,11305,12801,13741,13747,13981,14491,15709,15841,16705,18705,18721,19951,23001,23377,25761,29341,... https://oeis.org/a001567
161038、215326、2568226、3020626、7866046、9115426、49699666、143742226、161292286、196116194、209665666、213388066、293974066、336408382、376366、666、566、566、666 2001666066、2138882626、295226706.32200418 。 https://oeis.org/a006935
作为解决方案,请通过下面的链接获取这些号码的列表,以确保您测试的号码不在此列表中。 http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
C#的解决方案如下。
public static bool IsPrime(ulong number)
{
return number == 2
? true
: (BigInterger.ModPow(2, number, number) == 2
? (number & 1 != 0 && BinarySearchInA001567(number) == false)
: false)
}
public static bool BinarySearchInA001567(ulong number)
{
// Is number in list?
// todo: Binary Search in A001567 (https://oeis.org/A001567) below 2 ^ 64
// Only 2.35 Gigabytes as a text file http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
}