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