Groovy BigDecimal Прецизионная задача - PullRequest
3 голосов
/ 13 июня 2011

с учетом следующей строки

BigDecimal step = 10.0G**-1.0G

Groovy 1.7.5 возвращает неправильный

0.1000000000000000055511151231257827021181583404541015625

и Groovy 1.8 возвращает правильный

0.1

К сожалению, я хочу решить мою проблему в Grails. 1.4 с groovy 1.8 пока недостаточно стабилен (контроллеры не обновляются в режиме dev), а grails 1.3.7 поставляется с groovy 1.7.x

два вопроса:

  • я что-то не так делаю или это ошибка в 1.7.5?

  • как я могу избежать этого поведения? Я думаю, что BigDecimals идеально подходят для такого рода задач округления?

второе обновление: (забудьте первое обновление) -;

Теперь я немного запутался. кажется, что я получаю разные результаты каждый раз, когда я пытаюсь ....:

BigDecimal step = 10.0G**-1.0G
println step

возвращает 0.1000000000000000055511151231257827021181583404541015625

и

println 10.0G**-1.0G

возвращает

0.1

в обеих заводных версиях.

Но если вы просто поместите BigDec step = 10.0G**-1.0G в groovyConsole и позволите консоли напечатать последний ответ, вы получите разные результаты для разных версий groovy. Так что, похоже, одна из проблем - это groovyConsole.

Другая проблема - преобразование toString, которое выполняется.

И похоже, что происходит некоторая автобокс ... когда я делаю

def step = 10.0G**-1.0G

В результате получается Double ...

Полагаю, проблема сводится к двум вопросам:

  • a) какие математические операции являются операциями BigDecimal?

и

  • б) как я могу легко округлить BigDecimal, чтобы я мог исправить вышеупомянутую проблему?

Спасибо за терпение

Ответы [ 4 ]

4 голосов
/ 14 июня 2011

Думаю, у меня это есть. Вот подсказка из документа Java:

BigDecimal (двойное значение) Переводит двойное в BigDecimal, которое является точным десятичным представление двойного двоичного значение с плавающей точкой.

  • Итак, математические функции, которые я использую в своем коде, похоже, не поддерживают BigDecimal.
  • результат конвертируется за кулисы из Double в BigDecimal
  • точное представление двоичного двоичного числа равно 0.1000000000000000055511151231257827021181583404541015625, когда двойное число равно 0.1
  • println 10.0G**-1.0G печатает двойное значение (0.1)
  • BigDecimal step = 10.0G**-1.0G; println step печатает BigDecimal представление двойного 0.1, которое является уродливым числом выше

Кажется, что нет различий в поведении версий groovy (относительно BigDecimals), но есть различие в поведении того, как результат выводится в groovyConsole.

2 голосов
/ 13 июня 2011

Я использую Groovy 1.7.5 и для меня 10.0G**-1.0G возвращает 0.1

На каком JDK вы работаете?

1 голос
/ 30 сентября 2014

Если вы хотите преобразовать Double в BigDecimal и не получить все дополнительные цифры, один из способов сделать это - поместить Double в String, а затем преобразовать его в BigDecimal, что предотвратит появление всех дополнительных цифр. из точного двоичного представления двойного.

Double someFraction = 1.23456789
BigDecimal sameFraction = "${someFraction}".toBigDecimal()
1 голос
/ 13 июня 2011

Я подозреваю, что эти 10.0G ** - 1.0G превращаются в Math.pow (10, -1), math.pow возвращает удвоение, которое затем дает ошибку округления.Чтобы избежать этого, если вы повышаете только до -1, вы можете реализовать это как деление (1.0G / 10.0G).

Тем не менее, я не очень хорошо знаю Groovy, так что мое предположение можетошибаться, но это, безусловно, то, на что это похоже, и это подтверждается тем, что говорится в документах для Groovy.

...