2015-10-19 74 views
0

我想在一个long数据类型打印出每一个人号码,但我在大约10亿的数字收到此错误信息:打印出每个数字在“长”数据类型在Java中

抛出:IllegalArgumentException:从1072890159不合逻辑的文本范围到-1072593439

我该如何继续过去这一点?

long tot = 0; 
while (tot < 9223372036854775807L) 
{ 
    //This for loop makes sure that instead of printing out 200 000 numbers in 27 sec it 
    //will take less than 3 seconds to print out about 500 000 numbers 
    for (int i = 0; i < 10000; i++) 
    { 
     tot = tot + 10; 
     System.out.print(tot+" "+(tot+1)+" "+(tot+2)+" "+(tot+3)+" "+(tot+4)+" "+(tot+5) 
          +" "+(tot+6)+" "+(tot+7)+" "+(tot+8)+" "+(tot+9)+" "); 
    } 

    System.out.println(""); 
} 
+10

这是2^63的值;即使您每纳秒打印一个值(可能至少比现实快3个数量级),打印整个过程需要300年时间。 –

+0

我想猜你在使用Netbeans? – azurefrog

+2

这是NetBeans上的一个错误,实际上https://netbeans.org/bugzilla/show_bug.cgi?id=181582 –

回答

0

你不是“打印出来的long数据类型每一个人数”这个代码段。

首先,您从10开始打印正数。与byte尝试它来检查,但要准备快速中止运行,因为...

其次,while循环永远不会结束。为什么这个?

那么,一旦你花了appx。 150年(根据奥利弗·查尔斯沃斯的评论中提到的计算)totwhile标题变成9,223,372,036,854,700,000
tot总是的100,000for环由于‹0..9,999› < 10000+ 10其中之后的倍数。)

下面将在while周期中待打印(换行和格式化添加为便于阅读):

... 
9223372036854775800 9223372036854775801 9223372036854775802 
9223372036854775803 9223372036854775804 9223372036854775805 
9223372036854775806 9223372036854775807 -9223372036854775808 
-9223372036854775807 -9223372036854775806 -9223372036854775805 
-9223372036854775804 -9223372036854775803 -9223372036854775802 
... 

这就是所谓的(arithmetic) overflow

这样的tot对于另一个应用将会小于9223372036854775807L,也就是Long.MAX_VALUE。 150年,直到再次变为正值,然后整个周期重新开始,一遍又一遍。

为什么会发生这种情况?

那么,有一个且只有一个tot值,可以使(tot < 9223372036854775807L)评估为false离开while循环:正是这种9_223_372_036_854_775_807L,a.k.a Long.MAX_VALUE,因为没有比这个更大的long值。

但你是“隐藏”这个数字的for循环中(参见上面的输出,并记住,tot总是100,000 for环以外的倍数),这样(tot < 9223372036854775807L)永远不会来评估针对它的机会。

我会实现它,如下所示:

public class Integers { 

    public static void main(final String[] args) { 

     printNumbersBetween(Byte.MIN_VALUE, Byte.MAX_VALUE); 
     printNumbersBetween(Short.MIN_VALUE, Short.MAX_VALUE); 
     printNumbersBetween(Character.MIN_VALUE, Character.MAX_VALUE); 
     // printNumbersBetween(Integer.MIN_VALUE, Integer.MAX_VALUE); 
     // printNumbersBetween(Long.MIN_VALUE, Long.MAX_VALUE); 

    } // main(...) 

    public static void printNumbersBetween(final long minValue, final long maxValue) { 

     long n = minValue; 
     while (n < maxValue) { 
      // Count of numbers to be printed at once is preferably a power of two, 
      // since the counts of numbers in the domains of all primitives divide nicely by it. 
      // Such avoiding having to extra handle the last print cycle which is not "full". 
      // E.g.: byte -> 256 numbers -> (discouraged) chunks of 10 -> 25 * 10 + 6[!]. 
      System.out.printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d%n", 
       n++, n++, n++, n++, n++, n++, n++, n++, n++, n++, n++, n++, n++, n++, n++, n++); 
     } 

    } // printNumbersBetween(...) 

} // Integers 

除了上面让我离开你的有关编码风格的一些评论:

  • 9223372036854775807L是一样糟糕magic numbers可。 9_223_372_036_854_775_807L(自Java 7开始)稍微好一些,但是Java API正是为此提供了Long.MAX_VALUE
  • 我同意,人们可以辩论是否tot += 10tot = tot + 10;是首选。我不坚持这一点。
  • 的线条:

    System.out.printf("%d %d %d %d %d %d %d %d %d %d ", 
        tot, tot+1, tot+2, tot+3, tot+4, tot+5, tot+6, tot+7, tot+8, tot+9);` 
    

    相比:

    System.out.print(tot+" "+(tot+1)+" "+(tot+2)+" "+(tot+3)+" "+(tot+4)+" "+(tot+5) 
            +" "+(tot+6)+" "+(tot+7)+" "+(tot+8)+" "+(tot+9)+" "); 
    

    更容易阅读和理解,不是吗?而且它也更短。

  • System.out.println("");中创建(空)String的含义实例是毫无意义的。