Java - Decimal Format.parse to return double value with specified number of decimal places

前端 未结 4 776
隐瞒了意图╮
隐瞒了意图╮ 2020-12-09 18:50

I want to be able to convert a string to a Double given a number of decimal places in a format string. So \"###,##0.000\" should give me a Double

4条回答
  •  南笙
    南笙 (楼主)
    2020-12-09 19:35

    Taking on board what you said I have modified my code slightly to cover different locales. The key was taking a value string in a localised format to a Double that is rounded based on the format string.

    The format string is always a UK based format with the decimal seperators specified as "." and thousand seperators specified as ",".

    I am using the DecimalFormat to initially parse the localised format based on a specified locale. This gives a Double equivalent of the string correctly. I then use a BigDecimal to handle the rounding. I can get the number of decimal places from the DecimalFormat instance and call setScale on the BigDecimal to perform the rounding.

    The initial code structure has been modified to allow you to see what happens under different locale circumstances thanks @RD01 for noting importance of other locales.

    I now have code as follows:

    private void runTests3() {
        // output current locale we are running under
        System.out.println( "Current Locale is " + Locale.getDefault().toString() );
    
        // number in Central European Format with a format string specified in UK format
        String numbersInEuropeanFormatString[] = new String[] { "1.000,234567", "1,2345678", "1.222.333,234567" };
        String formatUK = "###,##0.0000";
    
        // output numbers using the german locale
        System.out.println("Output numbers using the German locale\n");
        for(String num : numbersInEuropeanFormatString ) {
            formatNumberAsDouble(num, formatUK, Locale.GERMAN);
        }
    
        // output numbers using the UK locale.  
        // this should return unexpected results as the number is in European format
        System.out.println("Output numbers using the UK locale\n");
        for(String num : numbersInEuropeanFormatString ) {
            formatNumberAsDouble(num, formatUK, Locale.UK);
        }
    
        // output numbers using new DecimalFormat( formatUK ) - no locale specified
        System.out.println("\n\nOutput numbers using new DecimalFormat( " + formatUK + " )\n");
        for(String num : numbersInEuropeanFormatString ) {
            formatNumberAsDouble( num, formatUK, null);
        }
    }
    
    private void formatNumberAsDouble(String value, String format, Locale locale) {
    
    
        NumberFormat formatter;
        int decimalPlaces;
    
        // create the formatter based on the specified locale
        if( locale != null ) {
             formatter = NumberFormat.getNumberInstance(locale);
             // creating the above number format does not take in the format string
             // so create a new one that we won't use at all just to get the
             // decimal places in it
             decimalPlaces = (new DecimalFormat(format)).getMaximumFractionDigits();
        } else {
            formatter = new DecimalFormat( format );
            decimalPlaces = formatter.getMaximumFractionDigits();
        }
    
        // get the result as number
        Double result = null;
        try {
            result = formatter.parse( value ).doubleValue();
        } catch( ParseException ex ) {
            // not bothered at minute
        }
    
        // round the Double to the precision specified in the format string
    
    
        BigDecimal bd = new BigDecimal(result );
        Double roundedValue = bd.setScale( decimalPlaces, RoundingMode.HALF_UP ).doubleValue();
    
        // output summary
        System.out.println("\tValue = " + value);
        System.out.println( locale == null  ? "\tLocale not specified" : "\tLocale = " + locale.toString());
        System.out.println( format == null || format.length() == 0 ? "\tFormat = Not specified" : "\tFormat = " + format);
        System.out.println("\tResult (Double) = " + result);
        System.out.println("\tRounded Result (Double) (" + decimalPlaces + "dp) = " + roundedValue);
        System.out.println("");
    }
    

    This produces the following output:

    Current Locale is nl_BE
    Output numbers using the German locale
    
        Value = 1.000,234567
        Locale = de
        Format = ###,##0.0000
        Result (Double) = 1000.234567
        Rounded Result (Double) (4dp) = 1000.2346
    
        Value = 1,2345678
        Locale = de
        Format = ###,##0.0000
        Result (Double) = 1.2345678
        Rounded Result (Double) (4dp) = 1.2346
    
        Value = 1.222.333,234567
        Locale = de
        Format = ###,##0.0000
        Result (Double) = 1222333.234567
        Rounded Result (Double) (4dp) = 1222333.2346
    
    Output numbers using the UK locale
    
        Value = 1.000,234567
        Locale = en_GB
        Format = ###,##0.0000
        Result (Double) = 1.0
        Rounded Result (Double) (4dp) = 1.0
    
        Value = 1,2345678
        Locale = en_GB
        Format = ###,##0.0000
        Result (Double) = 1.2345678E7
        Rounded Result (Double) (4dp) = 1.2345678E7
    
        Value = 1.222.333,234567
        Locale = en_GB
        Format = ###,##0.0000
        Result (Double) = 1.222
        Rounded Result (Double) (4dp) = 1.222
    
    
    
    Output numbers using new DecimalFormat( ###,##0.0000 )
    
        Value = 1.000,234567
        Locale not specified
        Format = ###,##0.0000
        Result (Double) = 1000.234567
        Rounded Result (Double) (4dp) = 1000.2346
    
        Value = 1,2345678
        Locale not specified
        Format = ###,##0.0000
        Result (Double) = 1.2345678
        Rounded Result (Double) (4dp) = 1.2346
    
        Value = 1.222.333,234567
        Locale not specified
        Format = ###,##0.0000
        Result (Double) = 1222333.234567
        Rounded Result (Double) (4dp) = 1222333.2346
    

提交回复
热议问题