「Java案例」利用方法求反素数

编写方法求求反素数

反素数(Emirp)是素数中一个有趣的变种,它本身是素数,反转后的数字也是素数,并且不能是回文数。

反素数基础实现

编写一个程序,要求编写方法public static boolean isPrime(int num)判断是否为素数;编写方法public static int reversal(int number)实现数字倒置;编写方法public static boolean isEmirp(int num)判断是否为反素数;编写方法public static void showEmirps(int count)显示前N个反素数。

java 复制代码
# 源文件保存为"EmirpNumbers.java"
public class EmirpNumbers {
    // 判断是否为素数
    public static boolean isPrime(int num) {
        if (num <= 1) return false;
        if (num == 2) return true;
        if (num % 2 == 0) return false;
        
        for (int i = 3; i * i <= num; i += 2) {
            if (num % i == 0) return false;
        }
        return true;
    }

    // 数字倒置
    public static int reversal(int number) {
        int reversed = 0;
        while (number != 0) {
            reversed = reversed * 10 + number % 10;
            number /= 10;
        }
        return reversed;
    }

    // 判断是否为反素数
    public static boolean isEmirp(int num) {
        int reversed = reversal(num);
        return num != reversed && isPrime(num) && isPrime(reversed);
    }

    // 显示前N个反素数
    public static void showEmirps(int count) {
        int found = 0, num = 2;
        while (found < count) {
            if (isEmirp(num)) {
                System.out.printf("%6d", num);
                if (++found % 10 == 0) System.out.println();
            }
            num++;
        }
    }

    public static void main(String[] args) {
        System.out.println("前30个反素数:");
        showEmirps(30);
    }
}

运行结果

makefile 复制代码
前30个反素数:
    13    17    31    37    71    73    79    97   107   113
   149   157   167   179   199   311   337   347   359   389
   701   709   733   739   743   751   761   769   907   937

代码解析

  • isPrime方法通过试除法判断素数,优化了偶数检查
  • reversal方法通过模运算和整数除法实现数字倒置
  • isEmirp方法组合前两个方法,并排除回文数情况
  • showEmirps方法从2开始逐个检查,直到找到足够数量的反素数

变体案例解析

双反素数

编写一个程序,要求编写方法public static boolean isPrime(int num)判断是否为素数;编写方法public static int reversal(int number)实现数字倒置;编写方法public static boolean isEmirp(int num)判断是否为反素数;编写方法public static void showDoubleEmirps(int count)寻找反转前后都是反素数的特殊数。

java 复制代码
# 源文件保存为"EmirpNumbers.java"
public class EmirpNumbers {
    // 判断是否为素数
    public static boolean isPrime(int num) {
        if (num <= 1) return false;
        if (num == 2) return true;
        if (num % 2 == 0) return false;

        for (int i = 3; i * i <= num; i += 2) {
            if (num % i == 0) return false;
        }
        return true;
    }

    // 数字倒置
    public static int reversal(int number) {
        int reversed = 0;
        while (number != 0) {
            reversed = reversed * 10 + number % 10;
            number /= 10;
        }
        return reversed;
    }

    // 判断是否为反素数
    public static boolean isEmirp(int num) {
        int reversed = reversal(num);
        return num != reversed && isPrime(num) && isPrime(reversed);
    }
    
    // 显示前N个双反素数
    public static void showDoubleEmirps(int count) {
        int found = 0, num = 2;
        while (found < count) {
            if (isEmirp(num)) {
                int reversed = reversal(num);
                if (isEmirp(reversed)) {
                    System.out.printf("(%d, %d) ", num, reversed);
                    if (++found % 3 == 0) System.out.println();
                }
            }
            num++;
        }
    }

    public static void main(String[] args) {
        System.out.println("前30个双反素数:");
        showDoubleEmirps(30);
    }
}

运行结果

makefile 复制代码
前30个双反素数:
(13, 31) (17, 71) (31, 13) 
(37, 73) (71, 17) (73, 37) 
(79, 97) (97, 79) (107, 701) 
(113, 311) (149, 941) (157, 751) 
(167, 761) (179, 971) (199, 991) 
(311, 113) (337, 733) (347, 743) 
(359, 953) (389, 983) (701, 107) 
(709, 907) (733, 337) (739, 937) 
(743, 347) (751, 157) (761, 167) 
(769, 967) (907, 709) (937, 739) 

发现:这个方法会找到像(13, 31)、(17, 71)这样的数字对。这类数字在密码学中有特殊意义,因为正反都可以作为密钥。

指定范围内的反素数

编写一个程序,要求编写方法public static boolean isPrime(int num)判断是否为素数;编写方法public static int reversal(int number)实现数字倒置;编写方法public static boolean isEmirp(int num)判断是否为反素数;编写方法public static void showEmirpsInRange(int start, int end)查找某个区间内的所有反素数。

java 复制代码
# 源文件保存为"EmirpNumbers.java"
public class EmirpNumbers {
    // 判断是否为素数
    public static boolean isPrime(int num) {
        if (num <= 1) return false;
        if (num == 2) return true;
        if (num % 2 == 0) return false;

        for (int i = 3; i * i <= num; i += 2) {
            if (num % i == 0) return false;
        }
        return true;
    }

    // 数字倒置
    public static int reversal(int number) {
        int reversed = 0;
        while (number != 0) {
            reversed = reversed * 10 + number % 10;
            number /= 10;
        }
        return reversed;
    }

    // 判断是否为反素数
    public static boolean isEmirp(int num) {
        int reversed = reversal(num);
        return num != reversed && isPrime(num) && isPrime(reversed);
    }

    public static void showEmirpsInRange(int start, int end) {
        int count = 0;
        for (int num = start; num <= end; num++) {
            if (isEmirp(num)) {
                System.out.printf("%6d", num);
                if (++count % 10 == 0) System.out.println();
            }
        }
        System.out.println("\n在" + start + "到" + end + "区间共找到" + count + "个反素数");
    }

    public static void main(String[] args) {
        System.out.print("反素数:");
        showEmirpsInRange(0, 30);
    }
}

实用技巧:当处理大范围时,可以预先筛选素数再判断反素数属性,提高效率。这种方法在数据分析时特别有用,比如统计千万级数字中反素数的分布规律。

反素数链

编写一个程序,要求编写方法public static boolean isPrime(int num)判断是否为素数;编写方法public static int reversal(int number)实现数字倒置;编写方法public static boolean isEmirp(int num)判断是否为反素数;编写方法public static void findEmirpChain(int length)查找找能形成多级反转仍为素数的数字链。

java 复制代码
# 源文件保存为"EmirpNumbers.java"
public class EmirpNumbers {
    // 判断是否为素数
    public static boolean isPrime(int num) {
        if (num <= 1) return false;
        if (num == 2) return true;
        if (num % 2 == 0) return false;

        for (int i = 3; i * i <= num; i += 2) {
            if (num % i == 0) return false;
        }
        return true;
    }

    // 数字倒置
    public static int reversal(int number) {
        int reversed = 0;
        while (number != 0) {
            reversed = reversed * 10 + number % 10;
            number /= 10;
        }
        return reversed;
    }

    // 判断是否为反素数
    public static boolean isEmirp(int num) {
        int reversed = reversal(num);
        return num != reversed && isPrime(num) && isPrime(reversed);
    }

    public static void findEmirpChain(int length) {
        int num = 2;
        while (true) {
            int current = num;
            boolean isChain = true;

            System.out.print("测试 " + num + ": ");
            for (int i = 0; i < length; i++) {
                System.out.print(current + " ");
                if (!isPrime(current)) {
                    isChain = false;
                    break;
                }
                current = reversal(current);
                if (current == reversal(current)) { // 排除回文
                    isChain = false;
                    break;
                }
            }

            if (isChain) {
                System.out.println(" ← 发现长度为" + length + "的反素数链");
                break;
            }
            System.out.println();
            num++;
        }
    }

    public static void main(String[] args) {
        findEmirpChain(3);
    }
}

运行结果

yaml 复制代码
测试 2: 2 
测试 3: 3 
测试 4: 4 
测试 5: 5 
测试 6: 6 
测试 7: 7 
测试 8: 8 
测试 9: 9 
测试 10: 10 
测试 11: 11 
测试 12: 12 
测试 13: 13 31 13  ← 发现长度为3的反素数链

有趣现象:当length设为3时,能找到像13→31→13这样的循环链。这类数字在数学游戏和谜题中很受欢迎。

实战练习题

基础题

优化素数判断 :修改isPrime方法,使用6k±1优化法(所有大于3的素数都可以表示为6k±1的形式),减少不必要的检查。

java 复制代码
# 源文件保存为"EmirpNumbers.java"
public class EmirpNumbers {
    // 判断是否为素数
    public static boolean isPrime(int num) {
        if (num <= 3) return num > 1;
        if (num % 2 == 0 || num % 3 == 0) return false;

        for (int i = 5; i * i <= num; i += 6) {
            if (num % i == 0 || num % (i + 2) == 0) {
                return false;
            }
        }
        return true;
    }

    // 数字倒置
    public static int reversal(int number) {
        int reversed = 0;
        while (number != 0) {
            reversed = reversed * 10 + number % 10;
            number /= 10;
        }
        return reversed;
    }

    // 判断是否为反素数
    public static boolean isEmirp(int num) {
        int reversed = reversal(num);
        return num != reversed && isPrime(num) && isPrime(reversed);
    }

    // 显示前N个反素数
    public static void showEmirps(int count) {
        int found = 0, num = 2;
        while (found < count) {
            if (isEmirp(num)) {
                System.out.printf("%6d", num);
                if (++found % 10 == 0) System.out.println();
            }
            num++;
        }
    }

    public static void main(String[] args) {
        System.out.println("前30个反素数:");
        showEmirps(30);
    }
}

提高题

反素数间距分析:编写方法分析反素数之间的间隔规律,找出最大间隔和平均间隔。

java 复制代码
# 源文件保存为"EmirpNumbers.java"
public class EmirpNumbers {
    // 判断是否为素数
    public static boolean isPrime(int num) {
        if (num <= 1) return false;
        if (num == 2) return true;
        if (num % 2 == 0) return false;

        for (int i = 3; i * i <= num; i += 2) {
            if (num % i == 0) return false;
        }
        return true;
    }

    // 数字倒置
    public static int reversal(int number) {
        int reversed = 0;
        while (number != 0) {
            reversed = reversed * 10 + number % 10;
            number /= 10;
        }
        return reversed;
    }

    // 判断是否为反素数
    public static boolean isEmirp(int num) {
        int reversed = reversal(num);
        return num != reversed && isPrime(num) && isPrime(reversed);
    }

    public static void analyzeEmirpGaps(int count) {
        int prev = 2, maxGap = 0, sumGaps = 0;
        int found = 0, num = 2;

        while (found < count) {
            if (isEmirp(num)) {
                int gap = num - prev;
                if (gap > maxGap) maxGap = gap;
                sumGaps += gap;
                prev = num;
                found++;
            }
            num++;
        }

        System.out.println("前"+count+"个反素数分析:");
        System.out.println("最大间隔: "+maxGap);
        System.out.println("平均间隔: "+(double)sumGaps/count);
    }

    public static void main(String[] args) {
        analyzeEmirpGaps(30);
    }
}

运行结果

makefile 复制代码
前30个反素数分析:
最大间隔: 312
平均间隔: 31.166666666666668

深入理解

反素数问题看似简单,却融合了数论、算法优化和编程技巧。素数判断的优化方法在实际密码学应用中至关重要,RSA加密算法就依赖大素数的快速判断。数字反转算法在处理身份证校验、信用卡号验证等场景也有广泛应用。

调试这类数字处理程序时,边界条件需要特别注意。比如数字0的反转、整型溢出(反转后的数字可能超过Integer.MAX_VALUE)、负数处理等。良好的做法是添加参数校验和异常处理:

性能方面,当需要查找大量反素数时,可以考虑使用埃拉托斯特尼筛法预先生成素数表,然后在这个表中查询反转数。这种方法用空间换时间,特别适合需要反复查询的场景。

相关推荐
David爱编程5 分钟前
JDK vs JRE:到底有什么本质区别?99% 的人都答不上来
java·后端
洛阳泰山42 分钟前
基于 Easy Rules 的电商订单智能决策系统:构建可扩展的业务规则引擎实践
java·开发语言·规则引擎·easy rules
THXW.1 小时前
【Java项目与数据库、Maven的关系详解】
java·数据库·maven
架构师沉默1 小时前
外卖平台每天1000万订单查询,是如何扛住高并发的?
java·后端·架构
kushu71 小时前
Java 包
java·开发语言
bug菌2 小时前
🤔领导突然考我Spring中的注解@Bean,它是做什么用的?我...
java·后端·spring
JavaArchJourney2 小时前
ArrayList 源码分析
java
寒士obj2 小时前
熟悉并使用Spring框架 - 注解篇
java·spring
BricheersZ2 小时前
LangChain4J-(1)-Hello World
java·人工智能·langchain
回家路上绕了弯2 小时前
Spring ApplicationContext 源码深度剖析:容器的核心引擎
java·spring