Как рассчитать целочисленное выражение в Java - PullRequest
1 голос
/ 16 ноября 2011

Предположим, мне нужно вычислить 3 * (2 / 3) = 2, но 3 * (2 / 3) = 0 в целочисленной арифметике.Итак, похоже, что я должен использовать арифметику с плавающей точкой 3 * (2.0 / 3) = 2.0 и приведение результат с плавающей точкой к int.

Имеет ли это смысл?Как бы вы избежали здесь кастинга?

Ответы [ 6 ]

5 голосов
/ 16 ноября 2011

В этом конкретном примере вам может быть лучше изменить выражение на 3 * 2 / 3 или 3 / 3 * 2.Таким образом, вы получите точный результат, используя только целочисленную математику.

Использование математики с плавающей точкой является более общим решением, но вы должны знать о проблемах округления.В общем, вы не должны ожидать, что x * (y / x) даст вам ровно y, когда x и y являются числами с плавающей точкой.

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

Math.round(3 * (2f / 3))

Просто приведение результат на int не является хорошимИдея, поскольку числа с плавающей точкой неточны, и такое приведение будет просто усекать число.

1 голос
/ 16 ноября 2011

Это из-за целочисленного деления.В таких выражениях вам лучше использовать float, да.

Вы можете избежать явного приведения, только если вы используете составной оператор.Составной оператор делает для вас автоматическое приведение.

int a = 3;
a *= (2.0/3);
System.out.println(a);
1 голос
/ 16 ноября 2011

Лично я бы перестроил уравнение так:

3 / 3 * 2 = 2

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

1 голос
/ 16 ноября 2011

* и / имеют одинаковый приоритет, поэтому, если пропустить скобки, вы получите правильный результат примера.

В противном случае приведение (или усечение) неизбежно.

1 голос
/ 16 ноября 2011

Вы не можете избежать каста. Вы можете использовать целочисленное деление или полное деление, но тогда аргументы и результат будут с плавающей точкой. Вы можете попробовать перемещаться по частям выражения, чтобы вывести целочисленное деление на верхний уровень. В вашем случае вы можете преобразовать 3 * (2 / 3) в (3 * 2) / 3, что приведет к 2 без каких-либо операций с плавающей запятой.

0 голосов
/ 26 ноября 2011

Чего именно вы хотите достичь? Используя целочисленную арифметику, результат зависит от того, где вы поставили круглые скобки. (a/b) * (c/d) * (e/f), как вы сами заметили, в целом приведет к чему-то отличному от (a*c*d) / (b*d*f), хотя математически оба выражения равны. Тем не менее, оба выражения могут быть правильными в зависимости от задачи, которую вы хотите решить. Я пропускаю четкое утверждение об этом.

Если вы ищете целое число, наиболее близкое к математически правильному значению, просто рассчитайте знаменатель и знаменатель отдельно, а затем выполните деление. Таким образом, промежуточные ошибки не возникают. Если нет, то вам нужно переформулировать свой вопрос.

...