Triangular number达到某个Nth的已知总和会收敛到
( n*(n+1) )/2
测试:
public static void main(String[] args) {
int n = 10;
long solution = (n * (n + 1)) / 2;
System.out.println("Num: " + n + " Solution: " + solution);
}
给出:
Num: 10 Solution: 55
如果我将号码增加到100000
int n = 100000;
long solution = (n * (n + 1)) / 2;
System.out.println("Num: " + n + " Solution: " + solution);
给出:
Num: 100000 Solution: 705082704
实际上应该是:
Num: 100000 Solution: 5000050000
将乘法更改为:
long solution = n;
solution = (solution * (n+1))/2;
System.out.println("Num: " + n + " Solution: " + solution);
似乎要修复它,但为什么long solution = (n * (n + 1)) / 2;
没有这样做?
答案 0 :(得分:5)
您正在执行int
算术,该算法在转换为long
之前会溢出。正如您所指出的那样,首先使用long
n
强制long
算术long
。数学运算完成后,值将提升为int
,此处溢出不会发生。
对n
使用int
时,数学运算为long
s,然后将结果转换为作业的{{1}}。
答案 1 :(得分:1)
你需要知道一个int的最大值,大约是2E9,你的计算是这样的:
1. (int * int) returns int
2. widening primitive conversion to long
因此,在原语转换为long之前,您的1E5 * 1E5 = 1E10会溢出。正如per the JLS:
如果整数乘法溢出,则结果是数学乘积的低阶位,用一些足够大的二进制补码格式表示
您的预期结果只是没有第33位的实际结果:
5,000,050,000 = 1 0010 1010 0000 0110 1011 0101 0101 0000
705,082,704 = 0010 1010 0000 0110 1011 0101 0101 0000
在开始算术之前使用很长时间可以避免这个问题。
答案 2 :(得分:0)
当您编写long solution = (n * (n + 1)) / 2;
时,算术将以int
执行,因为n
是int
,最后答案将转换为long
。< / p>
您要做的是将n
强制转换为long
,以便执行算术的时间很长,如下所示:
long solution = ((long)n * (n + 1)) / 2;