【问题标题】:Printing out every number in a "long" datatype in java在java中打印出“long”数据类型中的每个数字
【发布时间】:2015-10-19 21:58:04
【问题描述】:

我尝试打印出 long 数据类型中的每个单独的数字,但在大约 1,000,000,000 个数字后收到此错误消息:

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

【问题讨论】:

  • 这是 2^63 个值;即使您每纳秒打印一个值(可能比实际速度至少快 3 个数量级),打印整个值也需要 300 年。
  • 我猜你在用 Netbeans?
  • 这确实是 NetBeans 上的一个错误 netbeans.org/bugzilla/show_bug.cgi?id=181582

标签: java long-integer illegalargumentexception println


【解决方案1】:

您不是“打印出 long 数据类型中的每个数字”使用此代码 sn-p。

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

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

好吧,一旦你用了 appx. 150 年(根据 cmets 中提到的 Oliver Charlesworth 的计算)while 标头中的 tot 变为 9,223,372,036,854,700,000
totfor 循环之后始终是100,000 的倍数,因为其中有‹0..9,999› &lt; 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 &lt; 9223372036854775807L) 评估为 false 以离开 while 循环:正是这个 9_223_372_036_854_775_807L,a.k.a @ 987654344@,因为没有比这更大的long 值了。

但是你在for 循环中“隐藏”了这个数字(请参阅上面的输出并记住totfor 循环之外始终是100,000 的倍数)所以(tot &lt; 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

除了以上内容,让我留下一些关于你的编码风格的 cmet:

  • 9223372036854775807Lmagic numbers 一样糟糕。 9_223_372_036_854_775_807L(从 Java 7 开始)会稍微好一些,但 Java API 专门为此提供了 Long.MAX_VALUE
  • 我同意,可以争论是tot += 10 还是tot = 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 的隐式实例是没有意义的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-14
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-10
    相关资源
    最近更新 更多