unexpected behavior for the decimal places while convert a Double to a Float value (floating-point precision) using BigDecimal and DecimalFormat

huangapple go评论74阅读模式
英文:

unexpected behavior for the decimal places while convert a Double to a Float value (floating-point precision) using BigDecimal and DecimalFormat

问题

我想将一个 Double 转换为带有两位小数的 Float。

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;

class Scratch {
    private static final DecimalFormat df = new DecimalFormat("0.00");

    public static void main(String[] args) {
        Double worksAsIWouldExpect = 262143.05;
        Double worksNotAsIWouldExpect = 262144.05;

        convertAndPrint(worksAsIWouldExpect);
        // DecimalFormat: 262143.05
        // Big Decimal: 262143.05
        convertAndPrint(worksNotAsIWouldExpect);
        // DecimalFormat: 262144.06
        // Big Decimal: 262144.06
    }

    public static void convertAndPrint(Double doubleValue) {
        // DecimalFormat
        String stringValueDf = df.format(doubleValue);
        float floatValue = Float.parseFloat(stringValueDf);
        System.out.println("DecimalFormat: " + floatValue);

        // Big Decimal
        BigDecimal decimalValue = new BigDecimal(doubleValue.toString());
        decimalValue = decimalValue.setScale(2, RoundingMode.HALF_DOWN);
        floatValue = decimalValue.floatValue();
        System.out.println("Big Decimal: " + floatValue);
    }
}

输出:

DecimalFormat: 262143.05
Big Decimal: 262143.05
DecimalFormat: 262144.06
Big Decimal: 262144.06

我遇到的问题是,当使用“DecimalFormat”和“BigDecimal”方法转换值时,有时会得到不同的值(或者至少不是我期望的值)。

为什么 262144.05(Double)转换为 262144.06(Float),而不是 262144.05(Float)?

英文:

I would like to convert an Double to an Float with two decimal places.

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;

class Scratch {
    private static final DecimalFormat df = new DecimalFormat("0.00");
    
    public static void main(String[] args) {
        Double worksAsIWouldExpect = 262143.05;
        Double worksNotAsIWouldExpect = 262144.05;

        convertAndPrint(worksAsIWouldExpect);
        //DecimalFormat: 262143.05
        //Big Decimal: 262143.05
        convertAndPrint(worksNotAsIWouldExpect);
        //DecimalFormat: 262144.06
        //Big Decimal: 262144.06
    }

    public static void convertAndPrint(Double doubleValue) {
        //DecimalFormat
        String stringValueDf = df.format(doubleValue);
        float floatValue = Float.parseFloat(stringValueDf);
        System.out.println("DecimalFormat: " + floatValue);

        //Big Decimal
        BigDecimal decimalValue = new BigDecimal(doubleValue.toString());
        decimalValue = decimalValue.setScale(2, RoundingMode.HALF_DOWN);
        floatValue = decimalValue.floatValue();
        System.out.println("Big Decimal: " + floatValue);
    }
}

Output:

DecimalFormat: 262143.05
Big Decimal: 262143.05
DecimalFormat: 262144.06
Big Decimal: 262144.06

I have the problem that when converting the values with the "DecimalFormat" as well as with the "BigDecimal" -approach, i get sometimes different values (or at least ones i would not excpect)

Why is 262144.05 (Double) converting to 262144.06 (Float) and not to 262144.05 (Float)?

答案1

得分: 1

因为你在没有必要的情况下将数据转换为浮点数,从而引入了浮点表示错误。请注意,所有浮点数类型(即 float 和 double)都存在表示错误。如果要保持更高的精度,请不要转换为 float,如果可能的话也要避免使用 double。你可以通过直接将 doubleValue 转换为 BigDecimal 并打印 BigDecimal 来跳过一些转换。

BigDecimal decimalValue = new BigDecimal.valueOf(doubleValue);
decimalValue = decimalValue.setScale(2, RoundingMode.HALF_DOWN);
System.out.println("Big Decimal: " + decimalValue);

你还可以直接使用 BigDecimal 来配合 DecimalFormat 使用。

英文:

Because you are introducing floating point representation errors by converting to float without need. Note that all floating point types (ie float and double) have representation errors. If you want to keep more precise don't convert to float and if possible avoid double too. You can skip some of the transformations by converting doubleValue directly to BigDecimal and printing the BigDecimal too.

BigDecimal decimalValue = new BigDecimal.valueOf(doubleValue);
decimalValue = decimalValue.setScale(2, RoundingMode.HALF_DOWN);
System.out.println("Big Decimal: " + decimalValue);

You can also use DecimalFormat with the BigDecimal directly.

huangapple
  • 本文由 发表于 2023年5月24日 20:11:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76323409.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定