简体   繁体   English

在Java中以“长”数据类型打印出每个数字

[英]Printing out every number in a “long” datatype in java

I tried printing out every individual number in a long datatype but I get this error message after about 1,000,000,000 numbers: 我尝试打印出long数据类型中的每个数字,但在大约1,000,000,000个数字后收到此错误消息:

IllegalArgumentException: Illogical text range from 1072890159 to -1072593439 IllegalArgumentException:不合逻辑的文本范围从1072890159到-1072593439

How can I continue past this point? 我如何才能超越这一点?

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("");
}

You're NOT „ printing out every individual number in a long datatype “ with this code snippet. 您不会使用此代码段“以long数据类型打印出每个数字 ”。

Firstly, you start printing positive numbers from 10 on. 首先,从10开始打印正数。 Try it with byte to check but be prepared to abort the run quickly, since... 尝试用byte进行检查,但准备快速中止运行,因为...

Secondly, the while loop never ends. 其次, while循环永远不会结束。 Why this? 为什么这个?

Well, once you have spent appx. 好吧,一旦您花了约apx。 150 years (according to Oliver Charlesworth 's calculation mentioned in the comments) tot in the while header becomes 9,223,372,036,854,700,000 . 150年(根据评价提到奥利弗查尔斯沃思的计算) totwhile头变得9,223,372,036,854,700,000
( tot is always a multiple of 100,000 after the for loop due to the ‹0..9,999› < 10000 and the + 10 therein.) tot是总的倍数100,000for循环由于‹0..9,999› < 10000+ 10在其中。)

The following will be printed in that while cycle (line breaks and formatting added for easier reading): while循环中将打印以下内容(添加了换行符和格式以方便阅读):

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

This is known as (arithmetic) overflow . 这被称为(算术)溢出

Such tot will be less, since negative, than 9223372036854775807L , aka Long.MAX_VALUE , for another appx. 由于是负数,因此此tot会小于另一个Long.MAX_VALUE 9223372036854775807L (也称为Long.MAX_VALUE 150 years until it becomes positive again and then the whole cycle starts again, over and over. 150年,直到它再次变为正,然后整个循环又一次又一次地开始。

Why does this happen? 为什么会这样?

Well, there is one and only one value of tot that can make (tot < 9223372036854775807L) evaluate to false to leave the while loop: exactly this 9_223_372_036_854_775_807L , aka Long.MAX_VALUE , since there is no bigger long value than this. 好吧, 只有一个可以使(tot < 9223372036854775807L)tot(tot < 9223372036854775807L)评估为false以退出while循环:正是9_223_372_036_854_775_807L ,也就是Long.MAX_VALUE ,因为没有比这个更大的long值了。

But you are "hiding" this number inside the for loop (see output above and remember that tot is always a multiple of 100,000 outside the for loop) so that (tot < 9223372036854775807L) never gets the chance to evaluate against it. 但是,您是在“ for循环中“隐藏”此数字(请参见上面的输出,并记住,“ tot始终是for循环之外的100,000的倍数),因此(tot < 9223372036854775807L)永远没有机会对其进行评估。

I'd implement it as follows: 我将实现如下:

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

Apart from the above let me leave some comments concerning your coding style: 除了上述内容外,让我对您的编码风格发表一些评论:

  • 9223372036854775807L is as bad as magic numbers can be. 9223372036854775807L就像魔术数字一样糟糕。 9_223_372_036_854_775_807L (since Java 7) would be slightly better but Long.MAX_VALUE is provided by the Java API exactly for this. 9_223_372_036_854_775_807L (自Java 7起)会稍好一些,但Java API正是为此提供了Long.MAX_VALUE
  • I agree, one can argue whether tot += 10 or tot = tot + 10; 我同意,可以争论是tot += 10还是tot = tot + 10; is preferred. 是首选。 I don't cling on that. 我不坚持。
  • The lines: 这些行:

     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);` 

    compared to: 相比:

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

    are much easier to read and comprehend, aren't they? 更容易阅读和理解,不是吗? And it's shorter, too. 而且它也更短。

  • Creating an implicite instance of (an empty) String in System.out.println(""); System.out.println("");创建(空) String的隐式实例System.out.println(""); is pointless. 是没有意义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM