The realization of large integer arithmetic package (Java) (2)-fast power modulus, greatest common divisor, multiplication inverse element, prime number judgment, generation of large prime numbers

Previous blog implement large integer arithmetic package (Java) (1) - addition, subtraction, multiplication, division, modulo mode, modular addition (considered negative) , we realized the large number of basic addition, subtraction, multiplication, Divide, take the remainder. This blog will be based on them to achieve fast power modulus , greatest common divisor , multiplicative inverse element , prime number determination and generation of large prime numbers .

1. Fast power modulus

If we want to calculate 2 100 mod 19, the easiest way is to do 99 multiplications and then modulo 19.
But this will have two problems. 1. It will be time consuming to do multiplication all the time; 2. The number will eventually become very large and difficult to store,
so we will use fast exponentiation modulus (similar to the binary method), so we count 7 times That's it.
official
Among them, we will also use the following two formulas, so that the number we get is not very large.
official

   /**
	 * 快速幂取模
	 * @param one  底数
	 * @param two  指数
	 * @param mod  模
	 * @return     结果
	 */
	public static String Power(String one,String two,String mod) {
    
    
		if(two.equals("0")) {
    
       //0次幂结果为1
			//System.out.println("Power result=1");
			return "1";
		}else if(two.equals("1")){
    
       //1次幂结果为它本身
			return Mod(one, mod);
		}
		String count=two,result="1",temp=one;
		while(!count.equals("0")){
    
    
			if(Mod(count, "2").equals("1"))   //看它二进制最后一位是不是1
				result=Multiply(result, temp, mod);
			if(!count.equals("1"))    //这里避免最后一次做没用的乘法
				temp=Multiply(temp, temp, mod);
			count=Division(count, "2");   //次数减1,相当于二进制右移一位
		}
		//System.out.println(result);
		return result;
	}

Operation result:
2 5 mod 7 = 4
2 10 mod 13 = 10
2 100 mod 19 = 17
2 1000 mod 1777 = 1775
2 10000 mod 49999 = 100
2 100000 mod 998111 = 802658

Second, the greatest common divisor (Euclidean algorithm)

You can use Euclid's algorithm to find the greatest common divisor, also known as the tossing and dividing method.
Now find the greatest common divisor of 52 and 36:
Insert picture description here
When the remainder is 0, the divisor of the current formula is the greatest common divisor.

   /**
	 * 最大公约数
	 * @param one
	 * @param two
	 * @return     结果
	 */
	public static String GCD(String one,String two) {
    
    
		if(one.equals(two)) {
    
       //相等则GCD=任意一个
			//System.out.println("GCD="+one);
			return one;
		}
		int length1=one.length();
		int length2=two.length();
		String first=null,second=null,temp=null;
		if(length1>length2) {
    
       //保证第一个数大于第二个,当然也可以不用这么做
			first=one;
			second=two;
		}else if(length1<length2) {
    
    
			first=two;
			second=one;
		}else {
    
    
			for (int i = 0; i < length1; i++) {
    
    
				if(one.charAt(i)>two.charAt(i)) {
    
    
					first=one;
					second=two;
					break;
				}
				else if(one.charAt(i)<two.charAt(i)) {
    
    
					first=two;
					second=one;
					break;
				}
			}
		}
		while(!second.equals("0")) {
    
    
			temp=Mod(first, second);
			first=second;
			second=temp;
		}
		//System.out.println("GCD="+first);
		return first;
	}

Three, multiplicative inverse element (extended Euclidean algorithm)

If ab≡1 mod p and GCD(a,p)=1 (a and p are relatively prime), then the multiplicative inverse of a with respect to modulo p is called b.
Now use the extended Euclidean algorithm to find the multiplicative inverse of 15 modulo 41:
15 The multiplicative inverse of modulo 41 is 11.

   /**
	 * 扩展欧几里得算法
	 */
	static String x= "0",y= "0";
	public static String ExtendGCD(String a,String b) {
    
    
		if(b.equals("0")) {
    
    
			Operation.x="1";
			Operation.y="0";
			return a;
		}
		String d=ExtendGCD(b, Mod(a, b));
		String temp=Operation.x;
		Operation.x=Operation.y;
		Operation.y=Subtract(temp, Multiply(Division(a, b), Operation.y));
		//System.out.println("    "+Operation.x);
		//System.out.println("    "+Operation.y);
		return d;
	}
	/**
	 * 乘法逆
	 * @param a
	 * @param mod
	 * @return
	 */
	public static String MultiplicativeInverse(String a,String mod) {
    
    
		String d=ExtendGCD(a,mod);
		if(d.equals("1"))
			return Add(Mod(Operation.x, mod), mod, mod);
		return "-1";   //没有逆元
	}

Operation result:
5 modulo 23 multiplicative inverse element=14
28 modulo 75 multiplicative inverse element=67
83 modulo 108 multiplicative inverse element=95
119 modulo 4399 multiplicative inverse element=1109
49999 modulo 1234567 multiplicative inverse element=1078243

Fourth, the prime number determination (Miller Robin algorithm)

Description of Miller-Robin algorithm: The algorithm for
Miller Robin algorithm description
judging whether a number is prime or not is roughly as follows:
algorithm
Probability of misjudgment
Here I want to say that if the power-modulus algorithm in the algorithm is not selected properly, the time consumed by the entire Miller-Robin algorithm will be very scary...

/**
	 * 米勒罗宾算法
	 * @param one
	 * @return
	 */
	public static boolean MillerRabin(String one) {
    
    
		if(one.equals("0")||one.equals("1"))   //0和1不是素数
			return false;
		if(one.equals("2"))   //2是素数
			return true;
		if((one.charAt(one.length()-1)-48)%2==0)   //偶数不是素数
			return false;
		String number=Subtract(one, "1");   //计算n-1
		String number1=number;
		int count=0;
		while((number1.charAt(number1.length()-1)-48)%2==0) {
    
       //n-1=m*2^t
			number1=Division(number1, "2");
			count++;
		}
		for(int i=1;i<=5;i++) {
    
       //(a^(n-1))%n=(a^(m*2^t))%n
			String random=String.valueOf(i+2);
			String x=Power(random, number, one);   //(a^m)%n
			String y="";
			for(int j=1;j<=count;j++) {
    
       //((a^m)^(2^t))%n
				y=Multiply(x, x, one);
				if(y.equals("1")&&!x.equals("1")&&!x.equals(number))   //如果不满足二次探测定理,则不是素数
					return false;
				x=y;
			}
			if(!y.equals("1"))   //如果不满足费马小定理,则不是素数
				return false;
		}
		return true;
	}

Operation result:
111561511 is a composite number
564765326677 is a prime number
49841516591656517 is a composite number
555469971929450687843 is a prime number
262314699260834231863164359738235486290658375509 is a prime number
892209251968203592191654785870096688160362184103664355853918147486564850331 is a prime number

Five, generated large prime numbers

Insert picture description here

   /**
	 * 生成素数算法
	 * @return      素数
	 */
	public static String PrimeGeneration() {
    
    
	//一般来说,整除100以内的所有素数可排除76%不是素数的可能性,整除256以内的所有素数可排除80%
	//不是素数的可能性,所以创建小素数表,可以大幅加快速度,当然这个表可以手动生成
		String[] table= {
    
    "3","7","11","13","17","19","23","29","31","37","41","43","47",
				"53","59","61","67","71","73","79","83","89","97","101","103","107","109",
				"113","127","131","137","139","149","151","157","163","167","173","179",
				"181","191","193","197","199","211","223","227","229","233","239","241",
				"251","257","263","269","271","277","281","283","293","307","311","313",
				"317","331","337","347","349","353","359","367","373","379","383","389",
				"397","401","409","419","421","431","433","439","443","449","457",
				"461","463","467","479","487","491","499"};
		Random random=new Random();
		int flag;
		long time1=System.currentTimeMillis();
		while(true) {
    
    
			String number="";
			for(int i=1;i<=33;i++)   //生成一个随机的大奇数,这个位数任意取
				number+=String.valueOf(random.nextInt(899999998)+100000001);
			System.out.println(number);
			int num=random.nextInt(800)+101;   //后三位
			if(num%2==0)   //跳过偶数
				num++;
			for(int i=1;i<=50;i++,num+=2) {
    
       //搜索附近的50个奇数
				String temp="";
				if(num%5==0)   //跳过5的倍数
					num+=2;
				temp=temp+number+String.valueOf(num);
				flag=0;
				for(int j=0;j<table.length;j++) {
    
    
					if(Mod(temp, table[j]).equals("0")) {
    
       //看能不能被小整数整除
						flag=1;
						break;
					}
				}
				if(flag==1)
					continue;
				else
					if(MillerRabin(temp)) {
    
       //米勒罗宾算法
						System.out.println("素数: "+temp);
						System.out.println("时间差="+(System.currentTimeMillis()-time1)+"ms");
						return temp;
					}
			}
		}
	}

Operation results (300 decimal generating large prime numbers):
955042930633410289133616296687431777269353980956568253574985061454859846383784618868936295454149058329055354262839296541908590329891268218404276396709186373481902442299599349413886590143757678944807286223232776732690994758060943148907454012806238319657554857310557054678934303822406793932126613431907 is prime
time difference 369529ms =
886561163228838664750509032768759020351470065461506216295171421466522603290150530199373404129571069480539452635354057998985307892246327624821492158196842621382357442511837684610582698182410676560942977011624164506742932167839443913503332061016760221262755081522835308001246894308971214499396769460513 is prime
time difference = 29439ms
214870052980815367577291784627902708719802277128149369356311939236596853366271103968812931332145864571367016263259506949201985903708991330657005820918132219051420306215369688007649436101361885347977415827831904465125972681277283243530766501893543832374257674319643447978284232131374047798140761172317 is prime
time difference 143827ms

For the generated large prime numbers, we can use the Miller Robin algorithm we wrote earlier to detect. Of course, you can also use Java's BigInteger class to judge (use this class to generate large prime numbers very quickly, if you are interested, you can study it)

        String string="955042930633410289133616296687431777269353980956568253574985061454859846383784618868936295454149058329055354262839296541908590329891268218404276396709186373481902442299599349413886590143757678944807286223232776732690994758060943148907454012806238319657554857310557054678934303822406793932126613431907";
		BigInteger a=new BigInteger(string);
		if(a.isProbablePrime(1024))   a是素数的概率为1 - 1 / 2^1024
			System.out.println("素数");
		else
			System.out.println("合数");

Operation result: prime number

Six, source download

Implementation of Big Integer Package (Java)

Guess you like

Origin blog.csdn.net/H_X_P_/article/details/104110639