梅森尼数:2^n-1的素数
已经证

明了,如

果2^n-1是素数,则幂指数n必须是素数。但是反过来并不对。当n是素数时,2^n-1并不一定素数。

题目:给出需要找出指数n在[2,50]中的梅森尼数。

首先,分析题目可知,尽管梅森尼素数的逆命题是错误的,但是依然可以作为判断标准来减少循环数。

代码如下:

 1 public class Test_7 {
 2 
 3     public static void main(String[] args) {
 4         int count = 0;
 5         for(int i =2 ; i<=50 ; i++){
 6             if(IsPrime.isPrime(i)){
 7                 if(IsPrime.isPrime((int) Math.pow(2, i) - 1)){
 8                     System.out.println("2^"+i+"-1是梅森尼数:  "+((int) Math.pow(2, i) - 1));
 9                     count++;
10                 }
11             }
12         }
13         System.out.println("指数n在[2,50]中梅森尼数共有"+count+"个");
14     }
15 
16 }

这样编写显示出的梅森尼数只有7个,而按理说应该有8个,缺少的刚好是2^31-1;

网上搜索问题后发现int类型的最大值刚好是2^31-1,按理说应该并没有超出范围,查询代码后发现(int) Math.pow(2, 31)的结果为2^31-1,2^31超过int类型的最大值,导致在强制类型转换时,只能得到int的最大值2^31-1,导致后面判断素数时发生错误。

而后对代码的判断条件进行了修改,

if(IsPrime.isPrime((int)( Math.pow(2, i) - 1))){
                    System.out.println("2^"+i+"-1是梅森尼数:  "+((int) (Math.pow(2, i) - 1)));
                    count++;
                }

这样却导致程序误认为2^41-1,2^43-1,2^47-1也为梅森尼数。

最后将isprime函数的形参改为double类型,问题就解决了。

 

平时写程序时很少在使用int类型数时超出范围,导致并没有在意这个问题,以后还是要多注意各个数据类型的范围,防止数据溢出导致结果出错。

JAVA中各种数据类型的最值

int类型的最大值的常量可取的值为 2的31次方-1。理论上最大值是:214748364 

int类型的最小值的常量可取的值为 -2的31次方。理论上最少值是:-2147483648
 
float最值:   正负的3.4*10^38
 
Double的最值:正负的1.7*10^308
 
byte的取值范围为-128~127,占用1个字节(-2的7次方到2的7次方-1)
short的取值范围为-32768~32767,占用2个字节(-2的15次方到2的15次方-1)
 
long占64位,8个字节(-2的63次方到2的63次方-1)
最大值:9223372036854775807
long的定义
long l = 9223372036854775806L
注意后面的一个L,必须加上去。 

一个数组最大的长度是一个 int 的最大值,也就是 2147483647
而一个字符串在 Java 内部是使用 char[] 来表示的,也就是说一个字符串的最大长度是 2147483647
不过这些都是理论值,具体能放多少与 JVM 内存有关, 可以在执行 java 命令时加上 -Xmx 1024m 就将 JVM 内存最大置为了 1G, 默认情况下是 64MB.