【问题标题】:How Java processes for overflow integers [duplicate]Java如何处理溢出整数[重复]
【发布时间】:2013-06-29 14:14:21
【问题描述】:

现在 signed_int 最大值是 2,147,483,647 即 2^31 和 1 位是符号位,所以

当我运行long a = 2,147,483,647 + 1;

它给出a = -2,147,483,648 作为答案.. 这很好。 但是,24*60*60*1000*1000 = 86400000000(实际上)... 在 java 中,24*60*60*1000*1000 it equals to 500654080.. 我知道这是因为整数中的溢出,但是是什么处理使这个值来的,Java使用了什么逻辑来获取该数字。我也refered here

【问题讨论】:

  • 这应该是你感兴趣的 - stackoverflow.com/q/12758338/1679863
  • 这样想:24*60*60*1000*1000 = (((24*60)*60)*1000)*1000 并应用您在添加示例中执行的相同规则。
  • @jlordo 我想知道java是如何处理的
  • @Gru。你对什么过程感兴趣?去年我回答了一个类似的问题,我在之前的评论中已经链接了这个问题。你可以通过它。如果您仍有任何疑问,那么您可以要求澄清。
  • @RohitJain 类似?似乎完全一样。猜猜这个问题来自 Bloch 的益智文字。

标签: java math integer overflow long-integer


【解决方案1】:

乘法是这样从左到右执行的

    int x = 24 * 60;    
    x = x * 60;     
    x = x * 1000; 
    x = x * 1000;

前 3 个操作产生 86400000,仍然适合 Integer.MAX_VALUE。但是最后一个操作产生 86400000000 ,即十六进制的 0x141dd76000 。大于 4 的字节被截断,我们得到 0x1dd76000。如果我们打印它

System.out.println(0x1dd76000);

结果是

500654080

【讨论】:

    【解决方案2】:

    这是非常微妙的:在编写 long a = 2147483647 + 1 时,首先使用 ints 计算右侧,因为您提供了 int 文字。但这会在转换为long 之前循环到负数(由于溢出)。所以从int升级到long对你来说已经太晚了。

    为了规避这种行为,您需要通过后缀 L 将至少一个参数提升为长文字。

    这适用于所有使用文字的算术运算(也就是你的乘法):你需要将其中一个提升为长类型。

    通过查看可以看出您的乘法答案是 5006540​​80 的事实

    long n = 24L*60*60*1000*1000;
    long m = n % 4294967296L; /* % is extracting the int part so m is 500654080 
                                 n.b. 4294967296L is 2^32 (using OP notation, not XOR). */
    

    这里发生的情况是,您正在使用 int 类型“昼夜不停地”。是的,您丢失了进位位,但这与乘法无关。

    【讨论】:

    • 我想知道24*60*60*1000*1000怎么等于5006540​​80,是什么处理让java想出了这个数字
    • @Gru,我已经把和解放在我的回答中
    • 您的回答很好,但@Evgeniy Dorofeev 提供了逐步分析,+1 为您的回答...谢谢...
    【解决方案3】:

    因为 int 的范围是 -2,147,483,648 到 2,147,483,647。 因此,当您继续添加数字并超过最大限制时,它会从最左边的数字开始增益,即 -2,147,483,648,因为它是一个循环。您在问题中已经提到过。

    类似地,当您计算 24*60*60*1000*1000 时,这应该会导致 86400000000 按照数学计算。

    但实际上发生的事情是这样的:

    86400000000可以写成2147483647+2147483647+2147483647+2147483647+..36次+5006540​​80

    因此,将 2147483647 添加 40 次 结果 0 然后剩下 5006540​​80 最终导致5006540​​80

    我希望你清楚。

    【讨论】:

      【解决方案4】:

      在你的乘法中添加 L。如果您添加 L 而不是在 Long 范围内相乘,否则在 Integer 范围内溢出。尝试像这样相乘。

      24L*60*60*1000*1000
      

      这会给你一个正确的答案。

      【讨论】:

      • 我已经知道这个检查有问题的链接,我的问题是java如何处理并给出这样的数字。
      【解决方案5】:

      整数是 32 位长。为简单起见,让我们以一个 4 位长的数字为例。

      最大正值是:

      0111 = 7 (first bit is for sign; 0 means positive, 1 means negative)
      0000 = 0
      

      它的 min 负值是:

      1111 = -8 (first bit is for sign)
      1000 = -1
      

      现在,如果我们将此类型称为fbitfbit_max 等于 7。

      fbit_max + 1 = -8
      because bitwise 0111 + 1 = 1111
      

      因此,fbit_minfbit_max 的跨度为 16。从 -8 到 7。

      如果您将7*10 之类的值相乘并将其存储在fbit 中,结果将是:

      fbit number = 7 * 10 (actually 70)
      fbit number = 7 (to get to from zero to max) + 16 (min to max) + 16 (min to max) + 16 (min to max) + 15 (the rest)
      fbit number = 6
      

      【讨论】:

        【解决方案6】:
        24*60*60*1000*1000 = 86400000000
        

        使用MOD如下:86400000000 % 2147483648 = 5006540​​80

        【讨论】:

          猜你喜欢
          • 2011-08-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-17
          相关资源
          最近更新 更多