Java工具类-素数类
来源:互联网 发布:网络醉了是什么意思 编辑:程序博客网 时间:2024/06/11 09:27
引子
个人比较喜欢算法,在日常解题过程中,经常遇到各种跟素数有关的问题。为了方便未来使用,总结创建了素数工具类。
Prime类说明
Prime类用于处理素数相关问题,Prime类被设计为工具类,不允许创建实例,也不允许被继承,故以final修饰Prime类,并以private修饰默认构造器。
Prime类本身维护一个从2开始的素数列表(ArrayList),类初始化时,根据sInitPrimeListLength的值,初始素数列表长度为1000,在进行各种处理时会用到这个数组,特称由Prime类维护的素数数组为类列表。利用类列表,已经计算过的素数不会再重复计算,提高效率。
类列表衍生两个变量,一个是列表长度,即类列表维护的从2开始的素数的个数,可由函数getPrimeListLength()获得。另一个是已知最大素数,即类列表的最后一个元素,可由函数getMaxCheckedPrime()获得。这两个值在素数类内部被广泛使用。
Prime类常用的方法有以下几个:
1. int[] getPrimeArrayByLength(int length)
2. int[] getPrimeArrayBelow(int num)
3. int[] getPrimeArrayBetween(int startNum, int endNum)
Prime类提供判断是否为素数的方法:
1. boolean isPrime(int)
2. boolean isProbablePrime(String num, int certainty)
3. boolean isQuickPrime(int num)
Prime类还提供求最小公倍数和最大公约数的函数,以及其它方法,具体可以查看下面的函数列表。
函数列表
- int[] getPrimeArray()
将类列表中的素数转换为int数组返回 - int[] getPrimeArray(int start,int end)
将类列表中索引start至end的元素转换为int数组返回 - int[] getPrimeArray(int length)
将类列表中前length个素数转换为int数组返回 - int getPrimeListLength()
返回类列表中元素的个数 - int getMaxCheckedPrime()
返回类列表的最后一个元素 - boolean isPrime(int)
判断一个int整数是否为素数 - boolean isProbablePrime(String num, int certainty)
采用Miller-Rabin算法判断一个大整数是否为素数,可靠性为1-1/(2^certainty) - boolean isQuickPrime(int num)
利用类列表快速判断num是否为素数 - int[] getPrimeArrayByLength(int length)
返回长度为length的素数数组 - int[] getPrimeArrayBelow(int num)
返回小于等于num的素数数组 - int[] getPrimeArrayBetween(int startNum, int endNum)
返回startNum与endNum之间的素数组成的数组 - int getPrimeIndex(int num)
返回num在类列表中的索引,找不到返回-1 - int getPrimeIndex(int num, boolean isStrict)
返回num在类列表中的索引,找不到时,如果isStrict为true,则返回小于num的第一个元素的索引 - int binarySearch(int[] arr, int key)
在数组arr中查找key,如果找到则返回索引,找不到返回-1 - int binarySearch(int[] arr, int key, boolean isStrict)
在数组arr中查找key,找不到时,如果isStrict为true,则返回小于num的第一个元素的索引 - int Gcd(int a, int b)
返回a和b的最大公约数,如果a<=0或b<=0,则返回0 - int Gcd(int[] numArray)
返回数组内所有整数的最大公约数 - int Lcm(int a, int b)
返回a,b的最小公倍数 - int Lcm(int[] numArray)
返回数组内所有整数的最小公倍数
git代码仓库地址
下面是java源代码。对这个素数类有什么建议的可以在评论区提,我也在努力完善它。
码云git地址:http://git.oschina.net/bedbed/Euler/
最新版的代码在git上面,可能不会在这里更新。
素数类源码
package stone.math;import java.util.ArrayList;import java.util.Iterator;import java.lang.Math;import java.math.BigInteger;/* * Copyright (C) 2014-2016 Stone Chen * All rights reserved by Stone Chen * * Modification History: * Date Author Version Description * ----------------------------------------------- * 2016年9月13日 Stone Chen 1.0 [实现基本功能] * 2016年9月28日 Stone Chen 1.1 [添加判断大数是否为质数函数,调用BigInteger提供的方法] * 2016年10月27日 Stone Chen 1.2 [由维护数组改为维护集合] * *//** * [功能说明]素数工具类,工具类具有私有构造器,不允许创建实例,提供各种静态方法 */public final class Prime { /** [初始化时生成的sPrimeArray长度] */ private static final int sInitPrimeListLength = 1000; /** [从2开始的素数集合] */ private static ArrayList<Integer> sPrimeList = new ArrayList<Integer>(sInitPrimeListLength); /** * 类初始化代码块 */ static { getPrimeArrayByLength(sInitPrimeListLength); } /** * 工具类的私有构造器 */ private Prime() { } /** * [功能说明] 将primeList转换为int数组 * * @return int数组 */ public static int[] getPrimeArray() { int[] primeArray = new int[getPrimeListLength()]; for (int i = 0; i < primeArray.length; i++) { primeArray[i] = sPrimeList.get(i); } return primeArray; } /** * [功能说明] 将primeList的索引start至end的元素转换为int数组返回 * * @param start * 如果start < 0,那么start会被置为0 * @param end * 如果end < start,那么end会被置为start * @return 素数数组 */ public static int[] getPrimeArray(int start, int end) { if (start < 0) { start = 0; } if (end < start) { end = start; } int length = end - start + 1; int[] primeArray = new int[length]; for (int i = 0; i < length; i++, start++) { primeArray[i] = sPrimeList.get(start); } return primeArray; } /** * [功能说明] 返回从2开始的长度为length的素数数组 * * @param length * @return */ public static int[] getPrimeArray(int length) { if (length < 1) { length = 1; } return getPrimeArray(0, length - 1); } /** * [功能说明] 返回维护的素数集合的长度 * * @return */ public static int getPrimeListLength() { return sPrimeList.size(); } /** * [功能说明] 返回素数集合的最后一个元素 * * @return */ public static int getMaxCheckedPrime() { int listLength = getPrimeListLength(); if (listLength > 0) { return sPrimeList.get(getPrimeListLength() - 1); } return 1; } /** * [功能说明]判断一个数是否为素数 * * @param num * 待判断的整数 * @return num是素数返回true,否则返回false */ public static boolean isPrime(int num) { boolean flag = true; if (num < 2) { return false; } for (int i = 2; i * i <= num; i++) { if (num % i == 0) { flag = false; break; } } return flag; } /** * [功能说明]采用Miller-Rabin算法判断一个大整数是否为素数,可靠性为1-1/(2^certainty) * * @param num * 待判断的整数 * @return 是素数返回true */ public static boolean isProbablePrime(String num, int certainty) { BigInteger bigNum = new BigInteger(num); return bigNum.isProbablePrime(certainty); } /** * [功能说明]利用sPrimeList快速判断是否为素数 * * @param num * 待判断的整数 * @return 是否为素数 */ public static boolean isQuickPrime(int num) { if (num > getMaxCheckedPrime()) { boolean flag = true; int i = 0; for (; i < getPrimeListLength() && sPrimeList.get(i) <= Math.sqrt(num); i++) { if (num % sPrimeList.get(i) == 0) { flag = false; break; } } if (i == getPrimeListLength()) { for (int n = getMaxCheckedPrime(); n <= Math.sqrt(num); n++) { if (num % n == 0) { flag = false; break; } } } return flag; } if (getPrimeIndex(num) == -1) { return false; } return true; } /** * [功能说明]返回长度为length的素数数组 * * @param length * 返回的数组长度 * @return int素数数组 */ public static int[] getPrimeArrayByLength(int length) { // length<1则返回空数组 if (length < 1) { return new int[] {}; } // 如果length小于等于素数集合的长度,则将素数集合前length个元素转换为int数组返回 if (length <= getPrimeListLength()) { return getPrimeArray(length); } // length大于素数集合长度情况的处理 int count = getPrimeListLength(); for (int num = getMaxCheckedPrime() + 1; count < length; num++) { if (isPrime(num)) { sPrimeList.add(num); count++; } } return getPrimeArray(length); } /** * [功能说明]返回num以下的素数数组,不包括num * * @param num * 请求的素数数组上限 * @return 素数数组 */ public static int[] getPrimeArrayBelow(int num) { if (num < 2) { return new int[] {}; } // 如果num <= MaxCheckedPrime,则返回sPrimeList的子集的数组 if (num <= getMaxCheckedPrime()) { int index = getPrimeIndex(num, true); return getPrimeArray(index + 1); } // 将大于MaxCheckedPrime小于num的素数加入list for (int n = getMaxCheckedPrime() + 1; n < num; n++) { if (isPrime(n)) { sPrimeList.add(n); } } return getPrimeArray(getPrimeListLength()); } /** * [功能说明]返回startNum与endNum之间的素数数组,包括边界 * * @param startNum * 起点 * @param endNum * 终点 * @return 素数数组 */ public static int[] getPrimeArrayBetween(int startNum, int endNum) { // startNum>=endNum,如果startNum是素数,则返回单元素数组,否则返回空数组 if (startNum >= endNum) { if (isPrime(startNum)) { return new int[] { startNum }; } else { return new int[] {}; } } // startNum<endNum,startNum <= sPrimeList的最后一个元素 if (startNum <= getMaxCheckedPrime()) { int start = getPrimeIndex(startNum, true); if (start == -1 || sPrimeList.get(start) != startNum) { start++; } if (endNum <= getMaxCheckedPrime()) { int end = getPrimeIndex(endNum, true); return getPrimeArray(start, end); } else { for (int num = getMaxCheckedPrime() + 1; num <= endNum; num++) { if (isPrime(num)) { sPrimeList.add(num); } } return getPrimeArray(start, getPrimeListLength() - 1); } } // startNum<endNum,startNum > sPrimeList的最后一个元素 ArrayList<Integer> al = new ArrayList<>(); for (int num = startNum; num <= endNum; num++) { if (isPrime(num)) { al.add(num); } } int[] primeArray = new int[al.size()]; Iterator<Integer> it = al.iterator(); int i = 0; while (it.hasNext()) { primeArray[i++] = it.next(); } return primeArray; } /** * [功能说明]返回num在sPrimeList的索引,如果不存在则返回-1,用二分法查找 * * @param num * 待查找的整数 * @return index 索引 */ public static int getPrimeIndex(int num) { return getPrimeIndex(num, false); } /** * [功能说明]返回num在sPrimeList的索引,如果不存在则返回-1,用二分法查找 * * @param num * @param isStrict * 是否在找不到时返回小于num的第一个元素的索引 * @return 索引 */ public static int getPrimeIndex(int num, boolean isStrict) { int start = 0; int end = getPrimeListLength() - 1; while (start <= end) { int middle = (start + end) / 2; if (num < sPrimeList.get(middle)) { end = middle - 1; } else if (num > sPrimeList.get(middle)) { start = middle + 1; } else { return middle; } } // 若集合中找不到,是否返回小于key的最大数的索引 if (isStrict) { int result = start > end ? end : -1; return result; } return -1; } /** * [功能说明]用二分法在数组arr中查找key,找到返回索引,返回-1 * * @param arr * 待搜索的数组 * @param key * 关键字 * @return 索引值 */ public static int binarySearch(int[] arr, int key) { return binarySearch(arr, key, false); } /** * [功能说明]用二分法在数组arr中查找key,找到返回索引,否则根据isStrict标志返回 * * @param arr * 待搜索的数组 * @param key * 关键字 * @param isStrict * 是否要求在找不到key时返回小于key的最大值的索引 * @return 索引值 */ public static int binarySearch(int[] arr, int key, boolean isStrict) { int start = 0; int end = arr.length - 1; while (start <= end) { int middle = (start + end) / 2; if (key < arr[middle]) { end = middle - 1; } else if (key > arr[middle]) { start = middle + 1; } else { return middle; } } // 若数组中找不到,是否返回小于key的最大数的索引 if (isStrict) { int result = start > end ? end : -1; return result; } return -1; } /** * [功能说明] 返回a和b的最大公约数,如果a<=0或b<=0,则返回0 * * @param a * 正整数a * @param b * 正整数b * @return 最大公约数 */ public static int Gcd(int a, int b) { if (a <= 0 || b <= 0) { return 0; } int remainder = 0; while ((remainder = a % b) != 0) { a = b; b = remainder; } return b; } /** * [功能说明] 求数组内所有整数的最大公约数 * * @param numArray * 正整数数组 * @return 最大公约数 */ public static int Gcd(int[] numArray) { int gcd = numArray[0]; for (int i = 1; i < numArray.length; i++) { gcd = Gcd(gcd, numArray[i]); } return gcd; } /** * [功能说明] 求a,b的最小公倍数 * * @param a * 正整数a * @param b * 正整数b * @return 最小公倍数 */ public static int Lcm(int a, int b) { if (a <= 0 || b <= 0) { return 0; } int gcd = Gcd(a, b); return a / gcd * b; } /** * [功能说明] 求数组内所有整数的最小公倍数 * * @param numArray * 正整数数组 * @return 最小公倍数 */ public static int Lcm(int[] numArray) { int lcm = numArray[0]; for (int i = 1; i < numArray.length; i++) { lcm = Lcm(lcm, numArray[i]); } return lcm; }}
- Java工具类-素数类
- 趣味素数-素数 java
- java文件工具类
- java日期工具类
- java 绝对路径工具类
- java工具类
- Java 数据处理工具类
- java日期工具类
- java工具类Assert
- 一些Java工具类
- anroid&java工具类
- java StringUtil 工具类
- java身份证号工具类
- java 日期工具类
- Java开发工具类
- java 加密工具类
- java集合工具类
- java时间工具类
- JVM学习笔记(一)——本地方法栈及native方法
- Android 避免APP启动闪黑屏(Theme和Style)
- spring注解和springmvc容器初始化过程
- 【JavaScript】动态加载脚本和样式
- TCP/IP概述
- Java工具类-素数类
- 为什么要使用Base64?
- libpcap基础教程
- NestedScrollView嵌套RecyclerView时滑动不流畅问题的解决办法
- Linux tcpdump命令详解
- linux通过c语言编程访问远程mysql
- Android——Activity四种启动模式
- struts2通过FromData+ajax实现文件上传(页面无刷新)
- U-BOOT全线移植分析系列之三 ――U-BOOT在AT91RM9200上的移植