Ошибка в сравнении значений при использовании BigDecimal и compareTo() в Java
Уважаемые разработчики!
Стоит задача сравнить данные и сделать подсчеты. К сожалению после написания тестов выяснилось что метод работает не верно, пытался разобраться , считаю что ошибка в неправильном сравнении BigDecimal. Прошу ПОМОЧЬ НАЙТИ ОШИБКУ.
Заранее спасибо!
Задача :
PREMIUM_THEFT = SUM_INSURED_THEFT * COEFFICIENT_THEFT SUM_INSURED_THEFT - total sum insured of all policy's sub-objects with type "Theft" COEFFICIENT_THEFT - by default 0.11 but if SUM_INSURED_THEFT equal or greater than 15 then 0.05
( Где, SUM_INSURED_THEFT вводит сам пользователь а COEFFICIENT_THEFT расчитываеться в зависимости от числа которое ввели)
Код метода который реализует данную задачу :
@Override
public BigDecimal apply() {
if (value.compareTo(BigDecimal.ZERO) < 0) {
throw new IncorrectlyEnteredDataException("Value cannot be negative!");
} else if (value.compareTo(PREMIUM_DEFAULT_VALUE) >= 0) {
setCoefficientTheft(BigDecimal.valueOf(0.05));
} else if (value.compareTo(PREMIUM_DEFAULT_VALUE) < 0) {
setCoefficientTheft(BigDecimal.valueOf(0.11));
}
return value.multiply(getCoefficientTheft());
}
Тесты :
@Test
public void shouldCalculatePremiumTheftWithDefaultValue() {
RiskTypeTheft riskTypeTheft = new RiskTypeTheft(BigDecimal.valueOf(10));
BigDecimal actual = riskTypeTheft.apply();
assertEquals(BigDecimal.valueOf(0.5), actual);
}
//set_coefficient need to be 0.11 , actual = 20 * 0.11 = 2.2
@Test
public void shouldCalculatePremiumFireWithBiggerValue() {
RiskTypeTheft riskTypeTheft = new RiskTypeTheft(BigDecimal.valueOf(20));
BigDecimal actual = riskTypeTheft.apply();
assertEquals(BigDecimal.valueOf(2.2), actual);
}
Также ниже прикладываю скриншоты самого метода и класса + как отработали сами тесты :
Ответы (2 шт):
поменяйте
public BigDecimal apply() {
if (value.compareTo(BigDecimal.ZERO) < 0) {
throw new IncorrectlyEnteredDataException("Value cannot be negative!");
} else if (value.compareTo(PREMIUM_DEFAULT_VALUE) >= 0) {
setCoefficientTheft(BigDecimal.valueOf(0.11));
} else if (value.compareTo(PREMIUM_DEFAULT_VALUE) < 0) {
setCoefficientTheft(BigDecimal.valueOf(0.05));
}
return value.multiply(getCoefficientTheft());
}
и все тесты пройдут
На самом деле у вас несколько проблем. Действительно, сравнение выполняется неправильно. Помимо этого метод apply() излишне сложно реализован. И последнее - у вас проблема с тестами. Значения с плавающей точкой так сравнивать нельзя, нужно задавать дельту (т.е. допустимую погрешность), ведь это неточные значения.
public BigDecimal apply() {
if (value.compareTo(BigDecimal.ZERO) < 0)
throw new IncorrectlyEnteredDataException("Value cannot be negative!");
return value.compareTo(PREMIUM_DEFAULT_VALUE) < 0 ?
BigDecimal.valueOf(0.5) : value.multiply(BigDecimal.valueOf(0.11));
}
import java.math.BigDecimal;
import org.junit.Test;
import static org.junit.Assert.*;
public class RiskTypeTheftTest {
private final double delta = 0.1;
@Test
public void shouldCalculatePremiumTheftWithDefaultValue() {
RiskTypeTheft riskTypeTheft = new RiskTypeTheft(BigDecimal.valueOf(10));
double actual = riskTypeTheft.apply().doubleValue();
assertEquals(0.5, actual, delta);
}
//set_coefficient need to be 0.11 , actual = 20 * 0.11 = 2.2
@Test
public void shouldCalculatePremiumFireWithBiggerValue() {
RiskTypeTheft riskTypeTheft = new RiskTypeTheft(BigDecimal.valueOf(20));
double actual = riskTypeTheft.apply().doubleValue();
assertEquals(2.2, actual, delta);
}
}

