Java中的奇数数学错误

Java中的奇数数学错误,java,primes,primality-test,Java,Primes,Primality Test,我正在编写一个程序,用Java演示Miller-Rabin概率测试。代码基本完成了 import java.util.Random; import java.util.Scanner; /** * Program to demonstrate Miller-Rabin primality testing * * @author Nick Gilbert */ public class MillerRabin { public static void main(String[]

我正在编写一个程序,用Java演示Miller-Rabin概率测试。代码基本完成了

import java.util.Random;
import java.util.Scanner;

/**
 * Program to demonstrate Miller-Rabin primality testing
 * 
 * @author Nick Gilbert
 */
public class MillerRabin
{
    public static void main(String[] args)
    {
        //Setting up for algorithm
        Scanner in = new Scanner(System.in);
        Random rn = new Random();
        int n = 0, k = 0, m = 0, a = 0;
        double b = 0;
        boolean probablyPrime = false;

        //Asking user for an odd n
        do
        {
            System.out.print("Enter an odd number to test for primality: ");
            n = in.nextInt();
        }
        while(n % 2 == 0);

        //Calculating k and m
        m = n - 1;
        while(m % 2 == 0)
        {
            m /= 2;
            k++;
        }

        //Generating random a
        //a = rn.nextInt(n-1);

        //Outputting numbers that will be used in algorithm
        System.out.println("k = " + k);
        System.out.println("m = " + m);
        System.out.println();
        a = 86;
        System.out.println("A = " + a);

        //Running the algorithm
        //b_{0}
        b = Math.pow(a, m) % n;
        System.out.println("b0 = " + b);
        if(Math.abs(b) == Math.abs(1 % n)) //Dealing with +/- case via absolute value
        {
            probablyPrime = true;
        }
        else
        {
            //b_{1-(k-1)}
            for(int i = 1; i < k; i++) //Going to k-1
            {
                b = Math.pow(b, 2) % n;
                System.out.println("b" + i + " = " + b);
                if(Math.abs(b) == Math.abs(1 % n)) //Dealing with +/- case via absolute value
                {
                    probablyPrime = true;
                    break;
                }
            }
        }

        //Printing result
        if(probablyPrime)
        {
            System.out.println("Probably Prime");
        }
        else
        {
            System.out.println("Definitely Composite");
        }


    }
}
import java.util.Random;
导入java.util.Scanner;
/**
*Miller-Rabin素性测试演示程序
* 
*@作者尼克·吉尔伯特
*/
公共类MillerRabin
{
公共静态void main(字符串[]args)
{
//算法设置
扫描仪输入=新扫描仪(系统输入);
Random rn=新的Random();
int n=0,k=0,m=0,a=0;
双b=0;
布尔概率素=false;
//向用户询问奇数n
做
{
System.out.print(“输入奇数以测试素数:”);
n=in.nextInt();
}
而(n%2==0);
//计算k和m
m=n-1;
而(m%2==0)
{
m/=2;
k++;
}
//生成随机a
//a=n.nextInt(n-1);
//输出将在算法中使用的数字
System.out.println(“k=“+k”);
System.out.println(“m=”+m);
System.out.println();
a=86;
System.out.println(“A=“+A”);
//运行算法
//b_{0}
b=数学功率(a,m)%n;
System.out.println(“b0=“+b”);
if(Math.abs(b)==Math.abs(1%n))//通过绝对值处理+/-情况
{
probablyPrime=true;
}
其他的
{
//b_{1-(k-1)}
for(int i=1;i
我已经硬编码86作为我的a值来证明我的问题。当它第一次通过将a提高到m并取模n来计算b时,数学是不正确的。不是给86的b0,这是86^19%153的正确答案,而是给我b0等于107。我已经在调试器中检查了我的值,它们是正确的。我还检查了a^m的值,它给了我86^19,所以模数部分出现了问题。不幸的是,我不知道是什么把数学搞砸了

,Math.pow返回一个double,所以取double的模并没有帮助(千万不要对double取Mod,没人对你得到的负责)

请注意,(89^19)大约是2^122,因此无符号长(2^64-1)不能容纳这些数字。double的精度为2^53(千万不要使用double to mod,数论是基于整数的)。请尝试较小的值或使用该类。

设置了可能限制其精度的大小


Java拥有适合您的场景的类。

double
Java(以及任何IEEE系统)中的精度只有15-16位。如果使用大于此值的数字,则会出现表示错误

最有可能需要做的是使用BigInteger,它不仅可以处理任意精度,而且还具有针对幂和模优化的方法

// 86^19 % 153
BigInteger result = BigInteger.valueOf(86).modPow(BigInteger.valueOf(19), BigInteger.valueOf(153));
System.out.println(result);
印刷品

86

你能解释一下你期望
1%n
给你什么吗?这对我来说有点可疑。这不是我的问题所在,b的值在达到那个点之前就错了。我只是想了解你的代码在做什么,所以我可以帮助你。如果这里有一些不相关的部分,如果你把它们剥离出来,给我们一个简单的解释,这样我们就不会在不相关的部分上浪费时间,这将是非常有用的。在这种情况下,我想所有人都需要
System.out.println(Math.pow(86,19)%153)-并询问为什么不打印86。没有必要让我们读60-70行相当不透明的代码。Double的精度只有2^53,因为上面的位用于符号和指数。我只是好奇,这种modPow方法是否使用模幂运算?@TamimAdDari这种方法经过优化,因此它实际上不会计算
pow
部分,只有最后的结果。你可以对大指数进行测试,所用的时间是相当恒定的。