在 Java 中舍入浮点数时的奇怪行为

问题描述 投票:0回答:1

我需要实现一个小型度量转换器类,其主要任务是转换度量。例如,将米转换为英里。 另一个接受标准是以一位数的精度对结果进行四舍五入,除非数字小于 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。我想念什么?

java rounding
1个回答
0
投票

0.075
不能用绝对精度的
double
来表示。你可以看到,如果你打印
new BigDecimal(0.075)
的值:

0.07499999999999999722444243843710864894092082977294921875

这个数字肯定更接近 0.07,而不是 0.08,因此你得到了你所看到的结果。

© www.soinside.com 2019 - 2024. All rights reserved.