如何使用DecimalFormat将表示例如百分比,货币的数字值转换为字符串并返回BigDecimal

时间:2011-11-01 09:48:25

标签: java

您好我想知道如何格式化BigDecimal,表示数字,百分比,金额,整数到Locales中的String,从String返回BigDecimal。我正在使用功能强大的DecimalFormat,但我不确定如何在默认用户区域设置中使用转换为精确类型。我第一次使用它:

DecimalFormat.getCurrencyInstance().format( obj );
DecimalFormat.getCurrencyInstance().parse( source );

但是,由于数量庞大,其歪曲了它们的价值。所以我找到了一些东西并得到了这个:

DecimalFormat decimalFormat = new DecimalFormat();
decimalFormat.setParseBigDecimal( true );
BigDecimal bd = ( BigDecimal ) decimalFormat.parse( value );

但如何结合这些思考。我可能需要设置DecimalFormat一些在NumberFormat.get ??? instance()中使用的模式,但我不知道如何以及是否得到一些奇怪的行为。

那么请有经验的人帮助我吗?谢谢帕维尔

2 个答案:

答案 0 :(得分:1)

我认为您最好的选择是假设getCurrencyInstace()返回DecimalFormat,它可能会在所有“重要”区域设置中返回instanceof。为了安全起见,您可以使用public static BigDecimal parseCurrencyPrecise (String value) { NumberFormat format = NumberFormat.getCurrencyInstance (); if (format instanceof DecimalFormat) ((DecimalFormat) format).setParseBigDecimal (true); Number result = format.parse (value); if (result instanceof BigDecimal) return (BigDecimal) result; else { // Oh well... return new BigDecimal (result.doubleValue ()); } }

SimpleDateFormat

在我们的应用程序中,我们基本上会针对您需要DateFormat的不同内容执行相同操作,但在一般情况下只有{{1}}。

答案 1 :(得分:0)

过了一会儿写了这个。它似乎有效,但我不确定它是否能在所有时间都正常工作。也许它可以帮助别人。我也希望它不违反任何许可证。)

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Currency;
import java.util.Locale;

import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.text.NumberFormat;
import com.ibm.icu.util.UResourceBundle;

public class NumericHelper {

    public static BigDecimal parseStringToBigDecimal( String value, DecimalFormat decimalFormat ) throws ParseException {
        decimalFormat.setParseBigDecimal( true );
        return ( BigDecimal ) decimalFormat.parse( value );
    }

    /**
     * Extracted code from {@link NumberFormat#getPattern()} and
     * {@link java.text.NumberFormat#getInstance(Locale desiredLocale, int choice)} with some
     * modifications to get DecimalFormat with good Pattern
     * 
     * @param choice is static values from class {@link NumberFormat} eg
     *            {@link NumberFormat#INTEGERSTYLE}
     */
    public static DecimalFormat getDecimalFormatWithPattern( Locale desiredLocale, int choice ) {
        ICUResourceBundle rb = ( ICUResourceBundle ) UResourceBundle.getBundleInstance( ICUResourceBundle.ICU_BASE_NAME, desiredLocale );
        String[] numberPatterns = rb.getStringArray( "NumberPatterns" );

        DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance( desiredLocale );
        int entry = ( choice == NumberFormat.INTEGERSTYLE ) ? NumberFormat.NUMBERSTYLE : choice;
        DecimalFormat format = new DecimalFormat( numberPatterns[entry], symbols );

        if ( choice == NumberFormat.INTEGERSTYLE ) {
            format.setMaximumFractionDigits( 0 );
            format.setDecimalSeparatorAlwaysShown( false );
            format.setParseIntegerOnly( true );
        }
        else if ( choice == NumberFormat.CURRENCYSTYLE ) {
            adjustForCurrencyDefaultFractionDigits( format );
        }

        return format;
    }

    /**
     * Extracted from {@link DecimalFormat#adjustForCurrencyDefaultFractionDigits()} because it can
     * not be called
     */
    protected static void adjustForCurrencyDefaultFractionDigits( DecimalFormat decimalFormat ) {
        DecimalFormatSymbols symbols = decimalFormat.getDecimalFormatSymbols();

        Currency currency = symbols.getCurrency();
        if ( currency == null ) {
            try {
                currency = Currency.getInstance( symbols.getInternationalCurrencySymbol() );
            }
            catch ( IllegalArgumentException e ) {
            }
        }
        if ( currency != null ) {
            int digits = currency.getDefaultFractionDigits();
            if ( digits != -1 ) {
                int oldMinDigits = decimalFormat.getMinimumFractionDigits();
                // Common patterns are "#.##", "#.00", "#".
                // Try to adjust all of them in a reasonable way.
                if ( oldMinDigits == decimalFormat.getMaximumFractionDigits() ) {
                    decimalFormat.setMinimumFractionDigits( digits );
                    decimalFormat.setMaximumFractionDigits( digits );
                }
                else {
                    decimalFormat.setMinimumFractionDigits( Math.min( digits, oldMinDigits ) );
                    decimalFormat.setMaximumFractionDigits( digits );
                }
            }
        }
    }
}

在接下来的一段时间之后我想到了 NumberFormat.get *** Instance()方法,它返回它的后代类( DecimalFormat ) 。我不确定这是如何工作的,但它确实有效。在代码中是时刻,试图从LocaleServiceProviderPool获取格式,所以我相信它也会返回DecimalFormat,如果有的话,那没问题使用这个原始方法并转换为DecimalFormat但是如果不是,你必须检查。在代码中我写的是这部分省略