Почему Java BigDecimal stripTrailingZeros приводит к научной нотации

#java #native #bigdecimal #strip #trailing

#Ява #родной #bigdecimal #Стриптиз #задний

Вопрос:

Когда вы используете stripTrailingZeros для числа, заканчивающегося нулем, например, 10, 50 и т.д., BigDecimal.toString() Метод решил использовать научную нотацию ( вместо 50 печатает 5E 1) Вот пример кода, протестированного с помощью java 17:

 public static void main(String[] asd) {  // prints: "with stripTrailingZeros: 5E 1"  System.out.println("with stripTrailingZeros: "   new BigDecimal("50").stripTrailingZeros());   // prints: "without stripTrailingZeros: 50"  System.out.println("without stripTrailingZeros: "   new BigDecimal("50").toString()); }  

Я знаю, что оба они верны, но мне интересно, почему оба не возвращают «50»?

Это несоответствие раздражает, потому что оно распространяется по всему приложению и в моем случае приводит к несоответствию в моем API JSON, который ориентирован на клиента (читается людьми).

Я знаю, что могу исправить это с помощью BigDecimal.toPlainString() , но мне кажется неправильным заставлять сериализатор (в моем случае Джексона) использовать этот метод с дополнительной настройкой только для этого случая.

Комментарии:

1. Прочитайте мой полный вопрос, и вы узнаете, почему toPlainString это не лучший выбор для меня

2. Это совершенно нормально и работает именно так, как BigDecimal и должно быть. Большие десятичные числа всегда хранятся как number * 10^n . Не имеет значения, является ли n положительным или отрицательным. toString() точно отражает точность сохраненного значения.

3. @LouisWasserman, я знаю, что оба они верны. Что меня беспокоит, так это разница в результате BigDecimal.toString (). Это непоследовательно в представлении

4.Да, и…? BigDecimal моделирует, с какой точностью вы определяете значение. stripTrailingZeros() говорит BigDecimal : «Забудьте о значении одной цифры. Даже не показывайте мне единственную цифру». 50 и 5E 1 отличаются BigDecimal с. new BigDecimal("50").equals(new BigDecimal("5E 1")) это ложь.

5. В «50»» 0″ является конечным нулем. Вы попросили объект снять их, и вы расстроены тем, что он это сделал?

Ответ №1:

Из документации API по stripTrailingZeros() :

Возвращает большое десятичное число, численно равное этому, но с любыми конечными нулями, удаленными из представления.

Чего еще вы ожидаете, что он вернется? «5»?

Комментарии:

1. нет, я ожидаю, что новый BigDecimal().toString() для обоих вернет «50», а не «50» и «5E 1».

2. поэтому вам просто не следует вызывать метод, который преобразует его в представление «5E 1» прямо перед тем, как вы неявно вызовете toString() ..

3. В моем случае это невозможно. Мне нужно использовать .stripTrailingZeros() , потому что иногда цифры похожи на 123.22000 и т. Д., И мне нужно удалить конечные нули

Ответ №2:

Спасибо @yshavit за его комментарий. Сосредоточившись на своем случае, работая с десятичными знаками и удаляя конечные нули в десятичной части, я совершенно забываю, что это также удалит нули из недифференцированной части. Таким образом, ожидается new BigDecimal("50").stripTrailingZeros().toString() , что он вернет «5E 1» (без конечных нулей) вместо «50» (с конечным нулем). Из stripTrailingZeros() документов:

Например, удаление конечных нулей из большого десятичного значения 600.0, которое имеет компоненты [BigInteger, масштаб], равные [6000, 1], дает 6E2 с компонентами [BigInteger, масштаб], равными [6, -2].

Комментарии:

1. Рад предоставить информацию, которая прояснила это. 🙂 Ура!