Подтвердить что ты не робот

Java For-loop изменяет числовой результат при изменении типа переменной цикла

Я написал программу для вычисления номера PI с помощью формулы Лейбница:

[Leibniz formula]

Я написал for-loop с типом инициализации "int", цикл работает отлично, но когда я изменил тип инициализации на "long", результат изменился. Это происходит только тогда, когда цикл превышает миллиард. Это делает "int-loop" вычисляет PI более точным, чем "длинный цикл". Я не знаю, почему это происходит. Пожалуйста, помогите мне понять эту проблему. Благодарю! и вот мой код.

public static void main(String[] args) {
    double result1 = 0;
    double result2 = 0;
    double sign = 1;

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

    for (long j = 0; j <= 1607702095; j++) {
        result2 += sign/(2 * j + 1);
        sign *= -1;
    }

    System.out.println("result1  " + result1 * 4);
    System.out.println("result2  " + result2 * 4);
    System.out.println("pi       " + Math.PI);
}

И результат:

result1  3.141592653576877
result2  3.1415926529660116
pi       3.141592653589793
4b9b3361

Ответ 1

На самом деле, ваш первый цикл имел бы int переполнение при вычислении (2 * i + 1), когда i достаточно велико, поэтому я не буду полагаться на его вывод.

Второй цикл, с другой стороны, создает более правильный вывод, поскольку (2 * j + 1) не переполняется, поскольку он выполняет умножение long.

Это означает, что "int-loop" вычисляет PI более точным, чем "длинный цикл"

Это, вероятно, просто совпадение, поскольку вычисления в переполнении цикла int.

Ответ 2

Потому что вы переполняете строку

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

Если значение 2*i пересекает максимальное целочисленное значение

int range -2,147,483,648 to 2,147,483,647, но когда вы делаете 2*i для большего значения, он пересекает этот диапазон.

Лучше придерживаться long, и это даст вам правильный результат.

Ответ 3

2 * i, когда я близок к концу вашего цикла переполняет максимальное значение int, которое равно 2147483647

Использование длинной операции не переполняется.

Правильная процедура использует длинный тип. Вероятно, потому что значения добавляются и удаляются вокруг правильного PI для какого-то странного поведения, переполнение моментально вычисляет значение, близкое к правильному PI.

Я полагаю, что изменение предела цикла for из нескольких значений изменит конечный результат на значение, которое находится далеко от правого PI.

Ответ 4

У вас есть переполнение целых чисел.

Максимальная емкость подписанного int равна (2 ^ 31) -1 или 2,147,483,647.

(1,607,702,095 * 2) составляет 3215404190, что больше, чем 2,147,483,647.

Когда вы меняете я на длинный, вы увеличиваете емкость я до (2 ^ 63) -1.

Ответ 5

Заметили, что каждый указывает на переполнение целых чисел, но вам может понадобиться решение. (Если у вас уже есть один, пожалуйста, проигнорируйте следующее:))

При переполнении в части (2 * i + 1) кода вам следует указать max i в цикле for на (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), но он будет работать для ОЧЕНЬ ДЛИТЕЛЬНОГО времени.