Java中的奇数数学错误
我正在编写一个程序,用Java演示Miller-Rabin概率测试。代码基本完成了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[]
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
部分,只有最后的结果。你可以对大指数进行测试,所用的时间是相当恒定的。