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;    }}
0 0
原创粉丝点击