我需要实现一个小型度量转换器类,其主要任务是转换度量。例如,将米转换为英里。 另一个接受标准是以一位数的精度对结果进行四舍五入,除非数字小于 0.1,则应四舍五入到两位数的精度。
我已经编写了以下舍入方法的程序:
public static String round(double input) {
DecimalFormat df;
if(input < 0.1) {
df = new DecimalFormat("#.##");
} else {
df = new DecimalFormat("#.#");
}
df.setRoundingMode(RoundingMode.HALF_UP);
Locale currentLocale = LocaleContextHolder.getLocale();
df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(currentLocale));
return df.format(input);
}
现在我编写了一些单元测试来验证代码。
package de.helper;
import org.junit.jupiter.api.Test;
import org.springframework.context.i18n.LocaleContextHolder;
import java.util.Locale;
import static org.assertj.core.api.Assertions.assertThat;
class MetricsConverterTest {
@Test
public void roundNumberWith1DigitAccuracy() {
//arrange
LocaleContextHolder.setLocale(Locale.GERMAN);
//act
String actualRoundDown = MetricsConverter.round(10.123456);
String actualRoundUp = MetricsConverter.round(10.153456);
//assert
assertThat(actualRoundDown).isEqualTo("10,1");
assertThat(actualRoundUp).isEqualTo("10,2");
}
@Test
public void roundSmallNumberWith2DigitAccuracy() {
//arrange
LocaleContextHolder.setLocale(Locale.GERMAN);
//act
String actualRoundDown = MetricsConverter.round(0.091);
String actualRoundUp = MetricsConverter.round(0.076);
//assert
assertThat(actualRoundDown).isEqualTo("0,09");
assertThat(actualRoundUp).isEqualTo("0,08");
}
@Test
public void roundSmallNumberWith2DigitAccuracyStrangeEdgeCase() {
//arrange
LocaleContextHolder.setLocale(Locale.GERMAN);
//act
String actualRoundUp = MetricsConverter.round(0.075);
//assert
assertThat(actualRoundUp).isEqualTo("0,08");
}
@Test
public void roundSmallNumberEdgeCase1DigitAccuracy() {
//arrange
LocaleContextHolder.setLocale(Locale.GERMAN);
//act
String actualRoundUp = MetricsConverter.round(0.095);
//assert
assertThat(actualRoundUp).isEqualTo("0,1");
}
}
但是测试方法
roundSmallNumberWith2DigitAccuracyStrangeEdgeCase
失败了。实际输出是“0.07”,但根据我的理解,它应该是 0.08。我想念什么?
值
0.075
不能用绝对精度的double
来表示。你可以看到,如果你打印new BigDecimal(0.075)
的值:
0.07499999999999999722444243843710864894092082977294921875
这个数字肯定更接近 0.07,而不是 0.08,因此你得到了你所看到的结果。