Преобразуйте double в BigDecimal и установите BigDecimal Precision

В Java я хочу взять двойное значение и преобразовать его в BigDecimal и распечатать его значение String с определенной точностью.

import java.math.BigDecimal;
public class Main {
    public static void main(String[] args) {
        double d=-.00012;
        System.out.println(d+""); //This prints -1.2E-4

        double c=47.48000;
        BigDecimal b = new BigDecimal(c);
        System.out.println(b.toString()); 
        //This prints 47.47999999999999687361196265555918216705322265625 
    }
}

Он печатает эту огромную вещь:

47,47999999999999687361196265555918216705322265625

а не

47.48

Причина, по которой я делаю преобразование BigDecimal, иногда двойное значение будет содержать много десятичных знаков (т.е. -.000012), а при преобразовании double в String будет выдано научное обозначение -1.2E-4. Я хочу сохранить значение String в ненаучной нотации.

Я хочу, чтобы BigDecimal всегда имел две единицы точности: "47.48". Может ли BigDecimal ограничить точность при преобразовании в строку?

Ответ 1

Он печатает 47.48000, если вы используете другой MathContext:

BigDecimal b = new BigDecimal(d, MathContext.DECIMAL64);

Просто выберите контекст, который вам нужен.

Ответ 2

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

В соответствии с javadoc поведение конструктора BigDecimal (double val) может быть неожиданным, если вы не принимаете во внимание это ограничение:

Результаты этого конструктора могут быть несколько непредсказуемыми. Один может предположить, что запись нового BigDecimal (0.1) в Java создает BigDecimal, который в точности равен 0,1 (немасштабированное значение 1, с масштаб 1), но на самом деле он равен 0,1000000000000000055511151231257827021181583404541015625. Это связано с тем, что 0,1 не может быть представлен точно как двойной (или, для этого материи, как двоичной фракции любой конечной длины). Таким образом, значение который передается конструктору, не точно равен 0,1, несмотря на это.

Итак, в вашем случае вместо использования

double val = 77.48;
new BigDecimal(val);

использование

BigDecimal.valueOf(val);

Значение, возвращаемое BigDecimal.valueOf, равно значению, вызванному вызовом Double.toString(double).

Ответ 3

Вы хотите попробовать String.format("%f", d), который будет печатать двойной в десятичной нотации. Не используйте BigDecimal вообще.

Что касается точности: вы сначала сохраняете 47.48 в double c, а затем создаете новый BigDecimal из этого double. Потеря точности заключается в назначении c. Вы могли бы сделать

BigDecimal b = new BigDecimal("47.48")

чтобы избежать потери точности.

Ответ 4

Он печатает фактическое точное значение double.

Double.toString(), который преобразует double в String s, не печатает точное десятичное значение ввода - если x - ваше двойное значение, оно выводит точно столько цифр, что x ближайший double к напечатанному значению.

Дело в том, что такого double нет точно в 47.48. Doubles хранят значения как двоичные дроби, а не как десятичные числа, поэтому не могут хранить точные десятичные значения. (Это то, что BigDecimal для!)

Ответ 5

Синтаксис String.format помогает преобразовывать двойные и BigDecimals в строки любой точности.

Этот код Java:

double dennis = 0.00000008880000d;
System.out.println(dennis);
System.out.println(String.format("%.7f", dennis));
System.out.println(String.format("%.9f", new BigDecimal(dennis)));
System.out.println(String.format("%.19f", new BigDecimal(dennis)));

Печать

8.88E-8
0.0000001
0.000000089
0.0000000888000000000

Ответ 6

почему бы не b = b.setScale(2, RoundingMode.HALF_UP);

Ответ 7

BigDecimal b = new BigDecimal(c).setScale(2,BigDecimal.ROUND_HALF_UP);

Ответ 8

В Java 9 следующее устарело:

BigDecimal.valueOf(d). <удаp > setScaleудаp > (2, BigDecimal. <удаp > ROUND_HALF_UPудаp > );

вместо этого используйте:

BigDecimal.valueOf(d).setScale(2, RoundingMode.HALF_UP);

Пример:

    double d = 47.48111;

    System.out.println(BigDecimal.valueOf(d)); //Prints: 47.48111

    BigDecimal bigDecimal = BigDecimal.valueOf(d).setScale(2, RoundingMode.HALF_UP);
    System.out.println(bigDecimal); //Prints: 47.48