更改循环变量类型时,Java For循环更改数值结果

时间:2016-01-05 11:18:04

标签: java numeric

我写了一个用Leibniz公式计算PI编号的程序:

[Leibniz formula]

我写了一个初始化类型的for循环是" int" ,循环工作正常,但当我将初始化类型更改为" long"结果发生了变化。这仅在循环时间超过十亿时才会发生。这使得" int - loop"计算PI比" long-loop"更准确。我不知道为什么会这样。请帮我理解这个问题。谢谢!这是我的代码。

def after_sign_in_path_for(resource)
  case resource.class
  when Technician
    new_services_path  
  when User
    root_path
  end
end

结果是:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int index_func(int number, int *array, int x);
int main(){
    int n;
    scanf("%d", &n);
    int *nums = (int*)malloc(n*sizeof(int));
    int i;
    for(i=0; i<n; i++) {
        scanf("%d", &nums[i]);
    }
    int j;
    int counter = 0;
    for(j=0; j<n-1; j++){
        if((abs(nums[j+1] - nums[j]) != abs(n-1)) && (abs((nums[j+1] - nums[j]) != 1)))
        {
            counter = 0;
        }   
        else
        {
            counter = 1;
        }
    }
    if(counter == 0){
        printf("ambiguous\n");
    }else{
        printf("non ambiguous\n");
    }
    free(nums);
    return 0;
}

5 个答案:

答案 0 :(得分:34)

实际上,当int足够大时,你的第一个循环会在(2 * i + 1)的计算中溢出i,所以我不会依赖它的输出。

另一方面,第二个循环产生更正确的输出,因为(2 * j + 1)不会溢出,因为它执行long乘法。

  

这使得“int-loop”计算PI比“long-loop”

更准确

这可能只是一个巧合,因为int循环中的计算溢出。

答案 1 :(得分:11)

因为你在线上溢出

result1 += sign/(2 * i + 1);

2*i的值越过最大整数值

int范围是-2,147,483,648 to 2,147,483,647,但是当您2*i获得更大的值时,它会越过该范围。

最好坚持使用long,这样可以提供正确的输出。

答案 2 :(得分:10)

2 * i 当我接近你的循环结束时溢出最大值 2147483647

使用long操作不会溢出。

正确的程序是使用长型。可能因为某些奇怪行为在正确的PI周围添加和删除了值,溢出会瞬间计算到更接近正确PI的值。

我认为更改少量值的for循环限制会将最终结果更改为距离正确PI更远的值。

答案 3 :(得分:9)

你有整数溢出

signed int的最大容量为(2 ^ 31)-1或2,147,483,647。

(1,607,702,095 * 2)为3215404190,大于2,147,483,647。

当你将i改为long时,你将i的容量增加到(2 ^ 63)-1。

答案 4 :(得分:7)

注意到每个人都指向整数溢出,但您可能需要一个解决方案。 (如果您已经有一个,请忽略以下:))

在代码的(2 * i + 1)部分出现溢出时,您应该将for循环中的i最大化为(Integer.MAX_VALUE / 2 - 1),这会导致:

for (int i = 0; i <= (Integer.MAX_VALUE / 2 - 1); i++) {
    result1 += sign/(2 * i + 1);
    sign *= -1;
}

你也可以使用(Long.MAX_VALUE / 2 - 1)对长篇文章进行操作,但它会运行很长时间。