Сохраняйте точность с двойным в Java - PullRequest
130 голосов
/ 27 ноября 2008
public class doublePrecision {
    public static void main(String[] args) {

        double total = 0;
        total += 5.6;
        total += 5.8;
        System.out.println(total);
    }
}

Приведенный выше код печатает:

11.399999999999

Как я могу получить это, чтобы просто напечатать (или быть в состоянии использовать его как) 11,4?

Ответы [ 20 ]

3 голосов
/ 18 марта 2010

Использовать java.math.BigDecimal

Двойные числа представляют собой двоичные дроби внутри, поэтому они иногда не могут представлять десятичные дроби с точностью до десятичного числа.

2 голосов
/ 18 марта 2010

Числа с плавающей запятой отличаются от действительных чисел тем, что для любого заданного числа с плавающей запятой существует следующий более высокий номер с плавающей запятой. То же, что целые числа. Между 1 и 2 нет целых чисел.

Нет способа представить 1/3 как число с плавающей точкой. Под ним есть поплавок, над ним есть поплавок, и между ними есть определенное расстояние. И 1/3 находится в этом пространстве.

Apfloat для Java утверждает, что работает с числами с плавающей запятой произвольной точности, но я никогда не использовал его. Наверное, стоит посмотреть. http://www.apfloat.org/apfloat_java/

Подобный вопрос задавался здесь раньше Высокоточная библиотека Java с плавающей запятой

2 голосов
/ 18 марта 2010

Компьютеры хранят числа в двоичном формате и не могут точно представлять числа, такие как 33.333333333 или 100.0. Это одна из хитрых вещей с использованием двойников. Вам придется просто округлить ответ, прежде чем показывать его пользователю. К счастью, в большинстве приложений вам не нужно так много десятичных знаков.

2 голосов
/ 27 ноября 2008

Умножьте все на 100 и сохраните их в длинных центах.

1 голос
/ 27 ноября 2008

Двойные числа - это приближения десятичных чисел в вашем исходном коде Java. Вы видите последствия несоответствия между двойным (это двоичное значение) и вашим источником (который является десятичным).

Java производит самое близкое двоичное приближение. Вы можете использовать java.text.DecimalFormat для отображения лучшего десятичного значения.

1 голос
/ 27 ноября 2008

Использовать BigDecimal. Он даже позволяет вам задать правила округления (например, ROUND_HALF_EVEN, которые минимизируют статистическую ошибку, округляя до четного соседа, если оба имеют одинаковое расстояние; то есть, оба с 1,5 и 2,5 округляют до 2).

0 голосов
/ 07 мая 2018

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

public static double sumDouble(double value1, double value2) {
    double sum = 0.0;
    String value1Str = Double.toString(value1);
    int decimalIndex = value1Str.indexOf(".");
    int value1Precision = 0;
    if (decimalIndex != -1) {
        value1Precision = (value1Str.length() - 1) - decimalIndex;
    }

    String value2Str = Double.toString(value2);
    decimalIndex = value2Str.indexOf(".");
    int value2Precision = 0;
    if (decimalIndex != -1) {
        value2Precision = (value2Str.length() - 1) - decimalIndex;
    }

    int maxPrecision = value1Precision > value2Precision ? value1Precision : value2Precision;
    sum = value1 + value2;
    String s = String.format("%." + maxPrecision + "f", sum);
    sum = Double.parseDouble(s);
    return sum;
}
0 голосов
/ 14 ноября 2015

Почему бы не использовать метод round () из класса Math?

// The number of 0s determines how many digits you want after the floating point
// (here one digit)
total = (double)Math.round(total * 10) / 10;
System.out.println(total); // prints 11.4
0 голосов
/ 21 мая 2010

Не тратьте свои силы, используя BigDecimal. В 99,9999% случаев вам это не нужно. Тип java double конечно приблизительный, но почти во всех случаях он достаточно точен Имейте в виду, что у вас есть ошибка в 14-й значащей цифре. Это действительно незначительно!

Чтобы получить хороший вывод, используйте:

System.out.printf("%.2f\n", total);
0 голосов
/ 18 марта 2010

Проверьте BigDecimal, он обрабатывает проблемы, связанные с арифметикой с плавающей точкой, как это.

Новый вызов будет выглядеть так:

term[number].coefficient.add(co);

Используйте setScale (), чтобы установить число десятичных знаков, которые будут использоваться.

...