BigDecimal для bignumber не работает правильно в значении с плавающей запятой

E сть BigDecimal Тип данных в Java. Когда я объявляю число 5190000000 как BigDecimal следующим образом:

BigDecimal a = new BigDecimal(5190000000L * 1.0F);

, он взволнован и виден следующий результат:

Output:
5190000128

в то время как я опускаю F как значение с плавающей точкой, это правильно, как это:

BigDecimal a = new BigDecimal(5190000000L * 1.0);

Output:
5190000000

Что это? и как параметр F допускает ошибку? Я действительно запутался!!!!

РЕДАКТИРОВАТЬ

Версия JDK составляет 1,8

4 ответа

Перед BigDecimal построено, выражение внутри скобок должно быть оценено в первую очередь.

Так, 5190000000 * 1.0F оценивается в float значение, но это значение не совсем 5190000000. Почему? Потому что 5190000000 не может быть точно представлен в float, Некоторая точность уже потеряна до того, как BigDecimal создано. Поэтому вывод, который вы видите, не является точным.

Во втором случае 5190000000 * 1.0 оценивается в double, а также double имеет достаточную точность, чтобы точно представлять 5190000000. Почему это оценивается в double на этот раз?, спросите вы. Так как 1.0F является литералом с плавающей точкой, и 1.0 это двойной литерал. И это решает тип выражения.

Чтобы получить точное значение, используйте строковый конструктор:

BigDecimal bd = new BigDecimal("5190000000");
bd = bd.multiply(BigDecimal.ONE); // if you insist on multiplying it by 1

Это ожидаемое поведение. Выражение 5190000000 * 1.0F оценивается как число с плавающей точкой, точность которого составляет от 6 до 7 десятичных цифр.

На самом деле, значение, которое вы в конечном итоге получите, является точным до 7 цифр.

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

Рекомендуется либо использовать String или же long конструкторы для BigDecimal, или valueOf фабричный метод, чтобы инициализировать BigDecimal, поскольку они с большей вероятностью сохранят необходимую вам точность.

причина- метод построения BigDecimal, тип параметра двойной. - Итак, ваш первый код будет сделан неявным преобразованием компилятором, что создаст некоторую проблему потери точности. - Но ваш второй код '1.0', тип по умолчанию - double, так что это правильно. - Другое дело, что для типа int максимальное значение равно 2147483647, ваш заданный параметр - 5190000000, что приведет к ошибке компиляции.

Другие вопросы по тегам