【问题标题】:Multiplying 2 (small) numbers gives negatives solution, not overflow...so why?将 2 个(小)数相乘给出负数解决方案,而不是溢出……那为什么呢?
【发布时间】:2014-07-06 13:26:17
【问题描述】:

我搜索并找到了与此问题相关的主题,但在所有这些主题中,原因都是溢出(结果对于 int 类型来说太大了,对吧?)。 但在这种情况下,结果小于 int 的最大值,并且仍然从 2 个正数中产生一个负数。我想知道为什么。

代码如下:

int s = (50*49*48*47*46*45);
out.println(s);

OUTPUT:
-1443597888

现在当我尝试 449 而不是 49 时:

int s = (50*449*48*47*46*45);
out.println(s);

OUTPUT:
1760488896

那么为什么会这样呢? 我通常想计算 (50*49*48*47*46*45)/(1*2*3*4*5*6) 但它一直给出否定的结果。

感谢您的帮助。

哦,是的,我正在使用 Java,是一个非常早期的初学者,所以我对发生的事情一无所知。谢谢。

【问题讨论】:

  • 请添加相关语言标签。
  • 你认为 int 的最大值是多少?
  • 我一般要计算(50*49*48*47*46*45)/(1*2*3*4*5*6) 所以,一般, 消除分子和分母中的公因数,就像手动计算该表达式一样。
  • @HighPerformanceMark,消除共同因素并非易事。在这里切换到更大的数据类型可能会更好。
  • @RYU:您可能希望使用BigInteger 类进行计算。

标签: java math int


【解决方案1】:

您选择的编程语言的“int”类型可能使用 32 位有符号整数表示。这意味着使用固定数量的位来表示一个数字,因此可以存储的数字范围是有限的。最常见的范围是 -2147483648 到 2147483647(或写法不同,-2^31 到 2^31-1),最好查阅您的编程语言的文档以进行确认。

所以,一个 int 只能在那个有限的范围内,但你的计算的实际结果 (50*49*48*47*46*45) 将是 11441304000,这远远超出了这个范围,所以其中一个乘法会导致溢出。

不同的编程语言和平台以不同的方式处理这个问题,但一个常见的结果是数字只是简单地环绕,因此 2147483647+1 将导致 -2147483648。其他编程语言会捕捉到这一点并产生错误。其他人将再次自动切换到更大的表示,因此您根本不会出现溢出,但可以处理任意大的数字。

您使用的语言似乎属于第一组静默溢出,因此您只会得到错误的结果。

【讨论】:

    【解决方案2】:

    您没有指定您使用的语言,也没有指定 int 表示的位数。但这似乎是一个溢出问题。

    从你的第二个例子:

    50*449*48*47*46*45104839704000,它是二进制的: 01100001101000111011101110110111000000

    但是你得到的结果是1760488896,它是二进制的: 00000001101000111011101110110111000000

    第一个位(开头的0110...)被切断了。

    似乎你有 32 位的 int 表示。代表11441304000 太小了——50*49*48*47*46*45 的结果。

    在这两种情况下你都会得到错误的结果。为什么它只在第一个例子中是负面的?

    11441304000 的二进制表示是

    010 10101001111101000111000111000000

    但只有 32(粗体)位适合您的整数变量。其中第一个是1,转换为负十进制值。

    【讨论】:

    • 我是一个使用 Java 的初学者,所以我现在对位一无所知..当表达式在数学上不正确时,我怎么能及早知道何时会给出否定结果? (仅“二进制”)谢谢。
    • 一个整数有它的最大值。如果您尝试对它进行更大的评估,您会得到一些错误的,可能是负值。我认为您的问题不是负值,而只是错误值。我不确定您是否注意到在第二个示例中(使用449)结果也是错误的。回答您的问题:要检测溢出,您可以尝试stackoverflow.com/questions/1657834/…
    【解决方案3】:

    正如其他人所指出的,问题在于计算 50*49*48 ... 太大而无法放入 Java int。您可以切换到更大的固定精度类型,即long,但随后您会遇到其他一些更大的参数的问题。我的建议是使用 Java 的 BigInteger 类型来存储结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      • 2015-11-19
      • 1970-01-01
      • 1970-01-01
      • 2020-02-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多