Как избежать потери точности при делении и приведении к int? - PullRequest
1 голос
/ 16 апреля 2010

У меня есть ситуация, когда мне нужно выяснить, сколько раз int переходит в десятичное число, но в некоторых случаях я теряю точность. Вот метод:

public int test(double decimalAmount, int divisor) {
  return (int) (decimalAmount/ (1d / divisor));
}

Проблема в том, что если я передам 1.2 в качестве десятичной суммы и 5 в качестве делителя, я получу 5 вместо 6. Как я могу переосмыслить это, чтобы я знал, сколько раз 5 переходит в десятичную сумму как целое число?

Ответы [ 3 ]

3 голосов
/ 16 апреля 2010

Результат вычисления, вероятно, примерно такой, как 5.999999999994, поскольку результат с плавающей запятой не обязательно является целым числом. Когда вы приводите к типу int, вы усекаете его, и в результате получается 5. Для другого аналогичного набора аргументов вы можете увидеть результат 6.0000000000002, и он даст вам 6.

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

Чтобы действительно делать то, что, как я думаю, вы хотите сделать, вам не нужно использовать double с или float с. Вам нужно java.util.BigDecimal - посмотрите, как это работает. Вы можете использовать его, чтобы «точно» умножить 5 и 1,2, чтобы получить 6.

3 голосов
/ 16 апреля 2010
public int test(double decimalAmount, int divisor) {
  return (int) (divisor * decimalAmount);
}

Очевидно, это просто умножение, а затем усечение. Почему вы думаете, что вам нужен этот метод?

1 голос
/ 16 апреля 2010

Операции с плавающей точкой не верны, они являются приблизительными. С помощью этого оператора вы можете получить, например, 5,9 в результате. Приведение его к int приводит к 5 (вместо 6). Попробуйте округлить вместо усечения:

public int test(double decimalAmount, int divisor) {
  return Math.round(divisor * decimalAmount);
}
...