Скобки и порядок операций
У меня есть функция в 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
с, остальные double
s.
Я оценил эти 2 выражения в отладчике за несколько итераций, и результаты в целом отличаются примерно на 0,3. Почему это происходит и почему один работает, а другой нет?
2 ответа
Если nf_ant
а также nf
являются int
s, ваша проблема в том, что вторая версия выполняет целочисленное деление, а не деление с плавающей запятой. Вы должны разыграть одного из них первым.
Давайте сравним следующие два выражения:
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 аргумента переводятся в число с плавающей запятой до вычисления.