Java Fermat&x27的实施问题;这是一个小怪物

Java Fermat&x27的实施问题;这是一个小怪物,java,primes,Java,Primes,这是我对费马小定理的实现。有人知道它为什么不起作用吗 以下是我遵循的规则: 设n为测试素性的数字 选择2和n-1之间的任意整数a 计算一个^n模 检查a^n是否为mod n 霉菌代码: 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); //c

这是我对费马小定理的实现。有人知道它为什么不起作用吗

以下是我遵循的规则:

  • 设n为测试素性的数字
  • 选择2和n-1之间的任意整数a
  • 计算一个^n模
  • 检查a^n是否为mod n
霉菌代码:

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个素数的列表。每当我输入这些数字中的任何一个,我得到的不是“真”,而是“假”


这就是我认为代码不起作用的原因。

在java中,双精度只有大约15到17位的有限精度。这意味着,虽然您可以计算
Math.pow(a,n)
的值,但对于非常大的数字,您无法保证一旦该值超过15位,您将得到准确的结果

如果a或n的值较大,您的计算将超过该限制。例如
Math.pow(3,67)
的值为
9.270946314789783e31
,这意味着最后3位之后的任何数字都将丢失。因此,在应用模运算后,无法保证得到正确的结果()

这意味着您的代码实际上并没有测试您认为它能做什么。这是浮点数的固有工作方式,必须改变保存值的方式才能解决此问题。您可以使用
long
,但是您会遇到溢出问题(long不能保存大于
2^64-1
的值,因此在
3^67
的情况下,您会遇到另一个问题


一种解决方案是使用一个设计用来容纳任意大数的类,如
biginger
,它是。

的一部分,正如其他人所指出的,取幂会很快溢出。例如,如果你选择一个数n来测试小到30的素性,而随机数a是20,20^30=大约10^39,这是有些东西>>2^90。(我的ln是10^39)

您想要使用,它甚至有您想要的确切方法:

public BigInteger modPow(BigInteger exponent, BigInteger m)
“返回一个BigInteger,其值为(^m)”


此外,我不认为测试2到n-1之间的单个随机数会“证明”任何东西。你必须循环遍历2和n-1之间的所有整数。

@evthim即使你使用了BigInteger类的modPow函数,你也无法得到你正确选择的范围内的所有素数。为了进一步澄清这个问题,你将得到范围内的所有素数,但你有的数不是素数。If使用BigInteger类重新排列此代码。当您尝试所有64位数字时,一些非素数也会写入。这些数字如下

34156164511051387172919052047146694371468154616601795783218481891110261105851130512801137411381144911570911670518701995123001233772576129341。。。

16103815326、2568226、3020626、7866046、9115426、49699666、14374226、161292286、196116194、209665666、213388066、293974066、336408382、376366、666、566、666 2001038066、213882626、2952654706、3220041826、。。。

作为一种解决方案,通过从下面的链接获取这些数字的列表,确保您测试的数字不在此列表中。

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
}

它以什么方式不工作?为什么是
rInt
val
Doubles值应该始终是
int
s?我会首先替换
if(a.equals(val)){return“True”;}否则{return“False”}
return a.equals(val);
-原因有两个。1)返回
布尔值
要比返回
字符串
简单得多,后者要么是
True
要么是
False
(或者是
True
或者
False
或者..?)。2) 它更短。是的,基本筛选比证明数字的素性(素性?素性?)更有效。但是,通过了解如何正确地编写算法,我们可以学到很多东西,包括编程和数学。