Скобки и порядок операций

У меня есть функция в Java, которая возвращает целое число. Я знаю, что он должен вернуть, поэтому я знаю, когда он работает правильно или нет. В любом случае, в некоторой точке цикла for есть эта строка кода:

Если я напишу это так

miuf = miuf_ant * nf_ant / nf - ((double) ((t - 1) * hist[t - 1]) / (double) nf);`

результат в порядке.

Если я напишу это так

miuf = (miuf_ant * (nf_ant / nf) - ((double) ((t - 1) * hist[t - 1]) / (double) nf));

результат далеко

nf_ant, nf а также t являются intс, остальные doubles.

Я оценил эти 2 выражения в отладчике за несколько итераций, и результаты в целом отличаются примерно на 0,3. Почему это происходит и почему один работает, а другой нет?

2 ответа

Решение

Если nf_ant а также nf являются ints, ваша проблема в том, что вторая версия выполняет целочисленное деление, а не деление с плавающей запятой. Вы должны разыграть одного из них первым.

Давайте сравним следующие два выражения:

miuf_ant * nf_ant / nf
miuf_ant * (nf_ant / nf)

Первый из них эквивалентен следующему по правилам Java:

(miuf_ant * nf_ant) / nf

Здесь происходит то, что продукт оценивается в первую очередь, и потому что miuf_ant является doubleрезультат также double, После этого то же самое происходит для подразделения.

В "плохом" (втором) случае, хотя, потому что оба оператора деления intс, результат также intтеряя точность операции, эффективно обрезая результат. Эта потеря точности затем переносится на продукт.

Во втором случае nf_ant / nf будет вычисляться в целочисленной арифметике, так как скобки означают, что он вычисляется сам по себе. Эта потеря остатка является причиной разницы.

В первом случае это умножается на miuf_ant который является типом с плавающей запятой. поскольку * а также / имеют одинаковый приоритет, все 3 аргумента переводятся в число с плавающей запятой до вычисления.

Другие вопросы по тегам