「Java案例」利用方法求反素数(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 个反素数。
# 源文件保存为“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 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); } }
运行结果
前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) 寻找反转前后都是反素数的特殊数。
# 源文件保存为“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 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); } }
运行结果
前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) 查找某个区间内的所有反素数。
# 源文件保存为“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("
在" + 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) 查找找能形成多级反转仍为素数的数字链。
# 源文件保存为“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); } }
运行结果
测试 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的形式),减少不必要的检查。
# 源文件保存为“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); }
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); } }
提高题
反素数间距分析 :编写方法分析反素数之间的间隔规律,找出最大间隔和平均间隔。
# 源文件保存为“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); } }
运行结果
前30个反素数分析:
最大间隔: 312
平均间隔: 31.166666666666668
深入理解
反素数问题看似简单,却融合了数论、算法优化和编程技巧。素数判断的优化方法在实际密码学应用中至关重要,RSA 加密算法就依赖大素数的快速判断。数字反转算法在处理身份证校验、信用卡号验证等场景也有广泛应用。
调试这类数字处理程序时,边界条件需要特别注意。比如数字0的反转、整型溢出(反转后的数字可能超过 Integer.MAX_VALUE)、负数处理等。良好的做法是添加参数校验和异常处理:
性能方面,当需要查找大量反素数时,可以考虑使用埃拉托斯特尼筛法预先生成素数表,然后在这个表中查询反转数。这种方法用空间换时间,特别适合需要反复查询的场景。