Целочисленное деление: как вы производите двойное число? - PullRequest
219 голосов
/ 30 июня 2010

Для этого блока кода:

int num = 5;
int denom = 7;
double d = num / denom;

значение d равно 0.0. Его можно заставить работать на кастинг:

double d = ((double) num) / denom;

Но есть ли другой способ получить правильный double результат? Я не люблю кастовать примитивов, кто знает, что может произойти.

Ответы [ 10 ]

145 голосов
/ 30 июня 2010
double num = 5;

Это позволяет избежать броска. Но вы обнаружите, что приведенные преобразования четко определены. Вам не нужно угадывать, просто проверьте JLS . int to double - расширяющееся преобразование. От §5.1.2 :

Расширение примитивных преобразований не потерять информацию об общем величина числового значения.

[...]

Преобразование типа int или long плавать, или долгое время двойной, может привести к потере точность - то есть результат может потеряться некоторые из наименее значимых битов Значение. В этом случае в результате значение с плавающей точкой будет правильно округленная версия целочисленное значение, используя IEEE 754 режим округления до ближайшего (§4.2.4) .

5 можно выразить ровно как двойное число.

93 голосов
/ 30 июня 2010

Что не так с примитивами приведения?

Если по какой-то причине вы не хотите разыгрывать, вы можете сделать

double d = num * 1.0 / denom;
65 голосов
/ 30 июня 2010

Я не люблю кастовать примитивов, кто знает, что может произойти.

Почему у вас иррациональный страх кастовать примитивов?Ничего плохого не случится, когда вы разыгрываете int на double.Если вы просто не уверены, как он работает, посмотрите его в Спецификация языка Java .Приведение int к double является расширяющим примитивным преобразованием .

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

double d = num / (double) denom;
25 голосов
/ 23 мая 2013

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

double d = 5 / (double) 20; //cast to double, to do floating point calculations

Обратите внимание, что при касте результата это не будет

double d = (double)(5 / 20); //produces 0.0
15 голосов
/ 14 апреля 2015

Приведите одно из целых чисел / оба целых числа к числу с плавающей запятой, чтобы принудительно выполнить операцию с математическим вычислением с плавающей точкой В противном случае целочисленное Math всегда является предпочтительным. Итак:

1. double d = (double)5 / 20;
2. double v = (double)5 / (double) 20;
3. double v = 5 / (double) 20;

Обратите внимание, что приведение результата не сделает этого. Потому что первое деление выполняется согласно правилу приоритета.

double d = (double)(5 / 20); //produces 0.0

Я не думаю, что есть какая-то проблема с кастингом, о котором вы думаете.

8 голосов
/ 07 апреля 2016

Типовое приведение - единственный способ


Получение double из целочисленного деления - нет другого способа без приведения (может быть, вы не будете делать это явно, ноэто произойдет).

Теперь есть несколько способов получить точное значение double (где num и denom имеют тип int и, конечно, сприведение ) -

  1. с явным приведением:

    • double d = (double) num / denom;
    • double d = ((double) num) / denom;
    • double d = num / (double) denom;
    • double d = (double) num / (double) denom;

но не double d = (double) (num / denom);

с неявным приведением:

  • double d = num * 1.0 / denom;
  • double d = num / 1d / denom;
  • double d = ( num + 0.0 ) / denom;
  • double d = num; d /= denom;

но не double d = num / denom * 1.0;
и не double d = 0.0 + ( num / denom );

2 голосов
/ 14 сентября 2015

используйте что-то вроде:

double step = 1d / 5;

(1d приведен к удвоению)

0 голосов
/ 16 августа 2017

Лучший способ сделать это -

int i = 3;
Double d = i * 1.0;

d is 3.0 now.
0 голосов
/ 25 апреля 2017

просто используйте это.

int fxd=1;
double percent= (double)(fxd*40)/100;
0 голосов
/ 02 сентября 2016

Вы можете рассмотреть обертывание операций.Например:

class Utils
{
    public static double divide(int num, int denom) {
        return ((double) num) / denom;
    }
}

Это позволяет вам посмотреть (только один раз), выполняет ли бросок именно то, что вы хотите.Этот метод также может быть проверен, чтобы убедиться, что он продолжает делать то, что вы хотите.Также не имеет значения, какой трюк вы используете, чтобы вызвать деление (вы можете использовать любой из ответов здесь), если это приводит к правильному результату.Везде, где вам нужно разделить два целых числа, теперь вы можете просто позвонить Utils::divide и поверить, что это правильно.

...