Условие ScoreAttained выдает арифматическое исключение - OptaPlanner

Используя оценку HARDSOFTBIGDECIMAL.

В файле конфигурации я установил для scoreAttained значение 0hard/0soft.

Я получаю эту ошибку:

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(Unknown Source)
at org.optaplanner.core.impl.score.buildin.hardsoftbigdecimal.HardSoftBigDecimalScoreDefinition.calculateTimeGradient(HardSoftBigDecimalScoreDefinition.java:96)
at org.optaplanner.core.impl.score.buildin.hardsoftbigdecimal.HardSoftBigDecimalScoreDefinition.calculateTimeGradient(HardSoftBigDecimalScoreDefinition.java:27)
at org.optaplanner.core.impl.termination.ScoreAttainedTermination.calculateSolverTimeGradient(ScoreAttainedTermination.java:50)
at org.optaplanner.core.impl.termination.OrCompositeTermination.calculateSolverTimeGradient(OrCompositeTermination.java:69)
at org.optaplanner.core.impl.termination.OrCompositeTermination.calculateSolverTimeGradient(OrCompositeTermination.java:69)
at org.optaplanner.core.impl.termination.PhaseToSolverTerminationBridge.calculatePhaseTimeGradient(PhaseToSolverTerminationBridge.java:80)
at org.optaplanner.core.impl.localsearch.DefaultLocalSearchSolverPhase.solve(DefaultLocalSearchSolverPhase.java:60)
at org.optaplanner.core.impl.solver.DefaultSolver.runSolverPhases(DefaultSolver.java:190)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:155)

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

решил проблему, расширив HARDSOFTBIGDECIMALSCOREDEFINITION и переопределив метод calculateTimeGradient(..). Здесь, когда метод разделения вызывается для BigDecimal, я округляю.


person Ali Shah    schedule 25.02.2014    source источник
comment
Можешь опубликовать свой звонок?   -  person Drewness    schedule 26.02.2014
comment
@Drewness Звонок здесь   -  person Geoffrey De Smet    schedule 26.02.2014
comment
Создана проблема Jira @AliShah Запрос на извлечение, чтобы исправить ее, пожалуйста :)   -  person Geoffrey De Smet    schedule 26.02.2014


Ответы (1)


Скорее всего, вы делите два числа, у которых есть точное частное, бесконечное.

Например: 1/3 = 0.33333...

Из документов:

Когда объект MathContext поставляется с настройкой точности 0 (например, MathContext.UNLIMITED), арифметические операции являются точными, как и арифметические методы, которые не принимают объект MathContext. (Это единственное поведение, которое поддерживалось в версиях до 5.)

Как следствие вычисления точного результата, настройка режима округления объекта MathContext с настройкой точности 0 не используется и, следовательно, не имеет значения. В случае деления точное частное может иметь бесконечно длинное десятичное разложение; например, 1 разделить на 3.

Если частное имеет бесконечное десятичное расширение и указано, что операция возвращает точный результат, создается исключение ArithmeticException. В противном случае возвращается точный результат деления, как и для других операций.

Итак, чтобы исправить это, вам нужно указать шкалу точности для BigDecimal, например:

x.divide(y, 2, RoundingMode.HALF_UP)

Где 2 — точность, а RoundingMode.HALF_UP — режим округления.

Подробнее об округлении можно прочитать здесь.

person Drewness    schedule 25.02.2014
comment
Отличный ответ. Как библиотеку, какой RoundingMode мы должны использовать? Я европеец, поэтому я думаю, что HALF_UP, но наши американские пользователи/разработчики предпочтут HALF_EVEN, а другие пользователи/разработчики из других регионов могут захотеть чего-то другого... С другой стороны, мне очень не нравится зависимость от локали в таких вычислениях. - person Geoffrey De Smet; 26.02.2014
comment
@GeoffreyDeSmet - Ну, я нахожусь в США и использую HALF_UP, но я думаю, это действительно зависит от вашей ситуации. Я вижу ваше затруднительное положение, но мне трудно сказать, так или иначе. Извиняюсь! - person Drewness; 26.02.2014