在java中使用long代替int会导致额外的溢出情况。为什么?
我为Hackerrank挑战编写了一个解决方案,其中我将大量数字求和到一个总变量中。当我使用ints时,我注意到我在一个测试用例中溢出,但所有其他测试用例都输出了正确的答案。当我将在java中使用long代替int会导致额外的溢出情况。为什么?,java,Java,我为Hackerrank挑战编写了一个解决方案,其中我将大量数字求和到一个总变量中。当我使用ints时,我注意到我在一个测试用例中溢出,但所有其他测试用例都输出了正确的答案。当我将total变量切换为long以避免溢出时,我在两个测试用例中开始溢出(与之前相同,另一个)。一旦我将total、numToSell和lastMax更改为longs,程序就会计算出正确的答案 什么会导致这种情况发生?我希望将变量从int移动到long不会导致溢出 import java.util.*; public c
total
变量切换为long以避免溢出时,我在两个测试用例中开始溢出(与之前相同,另一个)。一旦我将total
、numToSell
和lastMax
更改为longs,程序就会计算出正确的答案
什么会导致这种情况发生?我希望将变量从int移动到long不会导致溢出
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int T = in.nextInt();
while(T-->0)
{
int N = in.nextInt();
int[] price = new int[N];
for(int i = 0; i < N; ++i)
{
price[i] = in.nextInt();
}
int lastMax = price[N-1]; //works when this and numToSell are longs
int numToSell = 0;
long total = 0; //if this is also an int, only overflows in one case in my samples
for(int i = N - 2; i >= 0; --i)
{
if(price[i] <= lastMax)
{
++numToSell;
total -= price[i];
}
else
{
total += numToSell*lastMax;
lastMax = price[i];
numToSell = 0;
}
}
total += numToSell*lastMax;
System.out.println(total);
}
}
}
import java.util.*;
公共类解决方案{
公共静态void main(字符串[]args){
扫描仪输入=新扫描仪(系统输入);
int T=in.nextInt();
而(T-->0)
{
int N=in.nextInt();
整数[]价格=新整数[N];
对于(int i=0;i=0;--i)
{
如果(价格[i]是,因为这里
total += numToSell*lastMax;
如果numToSell
和lastMax
是int
,那就是整数乘法。int*int=int。然后将int
添加到long
中。当numToSell
时(或lastMax
)是一个长的乘法指令,特定的乘法指令将如您所期望的那样工作。我注意到您在两个位置执行该数学。我猜如果您只是将total
更改为long和leftnumToSell
并将lastMax
更改为int,那么numToSell*lastMax
仍然会溢出,并给出不正确的结果如果total、numToSell和lastMax都是整数,那么在某些情况下,可能会意外取消并给出正确答案。如果total很长,则不一定会发生这种情况,但其他都是整数
下面是一个循环的示例
prices = {2000001,2000000,2000000,2000000};
lastMax = 2000000;
numToSell = 0;
total = 0;
loop:
iteration 1:
numToSell = 1;
total = -2000000
iteration 2:
numToSell = 2;
total = -4000000 // oh no, we underflowed if we are int, but not long!
iteration 3:
total = -4000000 + (2 * 2000000) // let's take a deeper look at this below
numToSell = 0;
lastMax = 20000001
total += 0;
让我们看一看这行:总计=-4000000+(2*2000000)
如果total、numToSell和lastMax都是整数,则total=0。这是因为total下溢和(2*20000000)将以完全相同的方式溢出。因此这两个值将被抵消
如果它们都是长的,那么没有任何东西溢出,所以total=-40000000+(2*2000000)=0
如果total很长,那么当它被设置为-4000000时,total并没有下溢。但是,(2*2000000)是一个整数,它将溢出并变成一个负数。所以total不会是零
这种情况下,所有的int都可以工作,所有的long都可以工作,但是混合失败。你能提供导致问题的最小数量的输入数据吗?我想你可以使用调试器回答你自己的问题,也许还可以对变量的符号进行一些抽查。啊,你是对的。我知道intint可以做32位的乘法,但我认为numToSelllastMax太小,无法溢出int,但它们实际上可能是50k*100k=50亿。在我的特定示例案例中,最后一个合计操作是-1897992076+-426605980=1970369240,这在某种程度上是神奇的正确。法官似乎让这种情况发生在多个隐藏的测试案例上,而不是这个粒子第一个。