创建三角数的奇怪行为

时间:2015-01-09 19:50:27

标签: java

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;没有这样做?

3 个答案:

答案 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执行,因为nint,最后答案将转换为long。< / p>

您要做的是将n强制转换为long,以便执行算术的时间很长,如下所示:

long solution = ((long)n * (n + 1)) / 2;