【问题标题】:Java: Why does "long" number get negative?Java:为什么“长”数会变成负数?
【发布时间】:2015-11-13 09:23:52
【问题描述】:

我有这个代码:

    long i = 0;
    while (true) {  
        i += 10*i + 5;
        System.out.println(i);
        Thread.sleep(100);      
    }

为什么long i 在打印几次后变成负数?如果超出范围,不应该出现错误吗?

【问题讨论】:

标签: java long-integer


【解决方案1】:

如果在最大值之后增加一个数字,Java 不会抛出错误。如果您希望有这种行为,您可以使用 Java 8 中的 Math.addExact(long x, long y) 方法。如果您通过 Long.MAX_VALUE,此方法将抛出 ArithmeticException

Java 不抛出异常并且您收到负数的原因与数字的存储方式有关。对于长原语,第一个字节用于指示数字的符号(0 -> 正数,1 -> 负数),而其余字节用于数值。这意味着最大的正值Long.MAX_VALUE 将存储为 01111...111(0 后跟 63 位 1)。由于您向 Long.MAX_VALUE 添加了一个数字,您将开始接收负整数,因为符号字节变为 1。这意味着您有一个数字溢出,但 Java 不会引发此错误。

【讨论】:

    【解决方案2】:

    如果操作溢出,结果会回到最小值并从那里继续。

    没有抛出异常。

    如果您的代码可能溢出,您可以改用BigInteger

    【讨论】:

      【解决方案3】:

      Mathjavadoc 的摘录:

      “平台使用带符号的二进制补码整数算术与 int 和 long 原始类型。开发人员应选择原始类型以确保算术运算始终产生正确的结果,这在某些情况下意味着运算不会溢出值范围计算。最佳实践是选择原始类型和算法以避免溢出。"

      对于 Java 8:

      "在size为int或long且需要检测溢出错误的情况下,addExact、subtractExact、multiplyExact、toIntExact方法在结果溢出时抛出ArithmeticException。对于除法、绝对值等其他算术运算,递增、递减和取反溢出仅发生在特定的最小值或最大值时,应酌情检查最小值或最大值"

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-29
        相关资源
        最近更新 更多