Целочисленное деление: как вы производите double?

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

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

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

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

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

10 ответов


double num = 5;

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

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

[...]

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

5 может быть выражено точно как double.


что не так с кастингом примитивы?

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

double d = num * 1.0 / denom;

мне не нравится кастинг примитивов, кто знает, что может случиться.

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

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

double d = num / (double) denom;

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

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

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

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

приведите одно из целых чисел / оба из целого числа, чтобы плавать, чтобы заставить операцию выполняться с плавающей запятой Math. В противном случае integer 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

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


Тип Литья Является Единственным Способом


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

Итак, есть несколько способов, мы можем попытаться получить точные double значение (где num и denom are 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);

  1. С неявное приведение:

    • 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 );


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

double step = 1d / 5;

(1d-это удвоение)


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

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

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


просто использовать это.

int fxd=1;
double percent= (double)(fxd*40)/100;

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

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

d is 3.0 now.