`
zwhc
  • 浏览: 266014 次
  • 性别: Icon_minigender_1
  • 来自: 福州
社区版块
存档分类
最新评论

DecimalFormat 源码简单阅读

    博客分类:
  • java
UP 
阅读更多
DecimalFormat 源码简单阅读

最终应该是使用 subformat 来进行格式化的。

因为我主要是想看一下,"0000" 这种格式,源码里是如何进行格式化的,所以,其它细节忽略。

关注到这几行代码:
        char zero = symbols.getZeroDigit();
        int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero

        if (digitList.isZero()) {
            digitList.decimalAt = 0; // Normalize
        }

前缀 0 应该是这里添加的。
            if (!fractionPresent && result.length() == sizeBeforeIntegerPart) {
                result.append(zero);
            }


查看了一下 symbols.getZeroDigit()
写得真是复杂。。。

    private StringBuffer subformat(StringBuffer result, FieldDelegate delegate,
                                   boolean isNegative, boolean isInteger,
                                   int maxIntDigits, int minIntDigits,
                                   int maxFraDigits, int minFraDigits) {
        // NOTE: This isn't required anymore because DigitList takes care of this.
        //
        //  // The negative of the exponent represents the number of leading
        //  // zeros between the decimal and the first non-zero digit, for
        //  // a value < 0.1 (e.g., for 0.00123, -fExponent == 2).  If this
        //  // is more than the maximum fraction digits, then we have an underflow
        //  // for the printed representation.  We recognize this here and set
        //  // the DigitList representation to zero in this situation.
        //
        //  if (-digitList.decimalAt >= getMaximumFractionDigits())
        //  {
        //      digitList.count = 0;
        //  }

        char zero = symbols.getZeroDigit();
        int zeroDelta = zero - '0'; // '0' is the DigitList representation of zero
        char grouping = symbols.getGroupingSeparator();
        char decimal = isCurrencyFormat ?
            symbols.getMonetaryDecimalSeparator() :
            symbols.getDecimalSeparator();

        /* Per bug 4147706, DecimalFormat must respect the sign of numbers which
         * format as zero.  This allows sensible computations and preserves
         * relations such as signum(1/x) = signum(x), where x is +Infinity or
         * -Infinity.  Prior to this fix, we always formatted zero values as if
         * they were positive.  Liu 7/6/98.
         */
        if (digitList.isZero()) {
            digitList.decimalAt = 0; // Normalize
        }

        if (isNegative) {
            append(result, negativePrefix, delegate,
                   getNegativePrefixFieldPositions(), Field.SIGN);
        } else {
            append(result, positivePrefix, delegate,
                   getPositivePrefixFieldPositions(), Field.SIGN);
        }

        if (useExponentialNotation) {
            int iFieldStart = result.length();
            int iFieldEnd = -1;
            int fFieldStart = -1;

            // Minimum integer digits are handled in exponential format by
            // adjusting the exponent.  For example, 0.01234 with 3 minimum
            // integer digits is "123.4E-4".

            // Maximum integer digits are interpreted as indicating the
            // repeating range.  This is useful for engineering notation, in
            // which the exponent is restricted to a multiple of 3.  For
            // example, 0.01234 with 3 maximum integer digits is "12.34e-3".
            // If maximum integer digits are > 1 and are larger than
            // minimum integer digits, then minimum integer digits are
            // ignored.
            int exponent = digitList.decimalAt;
            int repeat = maxIntDigits;
            int minimumIntegerDigits = minIntDigits;
            if (repeat > 1 && repeat > minIntDigits) {
                // A repeating range is defined; adjust to it as follows.
                // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;
                // -3,-4,-5=>-6, etc. This takes into account that the
                // exponent we have here is off by one from what we expect;
                // it is for the format 0.MMMMMx10^n.
                if (exponent >= 1) {
                    exponent = ((exponent - 1) / repeat) * repeat;
                } else {
                    // integer division rounds towards 0
                    exponent = ((exponent - repeat) / repeat) * repeat;
                }
                minimumIntegerDigits = 1;
            } else {
                // No repeating range is defined; use minimum integer digits.
                exponent -= minimumIntegerDigits;
            }

            // We now output a minimum number of digits, and more if there
            // are more digits, up to the maximum number of digits.  We
            // place the decimal point after the "integer" digits, which
            // are the first (decimalAt - exponent) digits.
            int minimumDigits = minIntDigits + minFraDigits;
            if (minimumDigits < 0) {	// overflow?
                minimumDigits = Integer.MAX_VALUE;
            }

            // The number of integer digits is handled specially if the number
            // is zero, since then there may be no digits.
            int integerDigits = digitList.isZero() ? minimumIntegerDigits :
                    digitList.decimalAt - exponent;
            if (minimumDigits < integerDigits) {
                minimumDigits = integerDigits;
            }
            int totalDigits = digitList.count;
            if (minimumDigits > totalDigits) {
                totalDigits = minimumDigits;
            }
            boolean addedDecimalSeparator = false;

            for (int i=0; i<totalDigits; ++i) {
                if (i == integerDigits) {
                    // Record field information for caller.
                    iFieldEnd = result.length();

                    result.append(decimal);
                    addedDecimalSeparator = true;

                    // Record field information for caller.
                    fFieldStart = result.length();
                }
                result.append((i < digitList.count) ?
                              (char)(digitList.digits[i] + zeroDelta) :
                              zero);
            }

            if (decimalSeparatorAlwaysShown && totalDigits == integerDigits) {
                // Record field information for caller.
                iFieldEnd = result.length();

                result.append(decimal);
                addedDecimalSeparator = true;

                // Record field information for caller.
                fFieldStart = result.length();
            }

            // Record field information
            if (iFieldEnd == -1) {
                iFieldEnd = result.length();
            }
            delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
                               iFieldStart, iFieldEnd, result);
            if (addedDecimalSeparator) {
                delegate.formatted(Field.DECIMAL_SEPARATOR,
                                   Field.DECIMAL_SEPARATOR,
                                   iFieldEnd, fFieldStart, result);
            }
            if (fFieldStart == -1) {
                fFieldStart = result.length();
            }
            delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,
                               fFieldStart, result.length(), result);

            // The exponent is output using the pattern-specified minimum
            // exponent digits.  There is no maximum limit to the exponent
            // digits, since truncating the exponent would result in an
            // unacceptable inaccuracy.
            int fieldStart = result.length();

            result.append(symbols.getExponentSeparator());

            delegate.formatted(Field.EXPONENT_SYMBOL, Field.EXPONENT_SYMBOL,
                               fieldStart, result.length(), result);

            // For zero values, we force the exponent to zero.  We
            // must do this here, and not earlier, because the value
            // is used to determine integer digit count above.
            if (digitList.isZero()) {
                exponent = 0;
            }

            boolean negativeExponent = exponent < 0;
            if (negativeExponent) {
                exponent = -exponent;
                fieldStart = result.length();
                result.append(symbols.getMinusSign());
                delegate.formatted(Field.EXPONENT_SIGN, Field.EXPONENT_SIGN,
                                   fieldStart, result.length(), result);
            }
            digitList.set(negativeExponent, exponent);

            int eFieldStart = result.length();

            for (int i=digitList.decimalAt; i<minExponentDigits; ++i) {
                result.append(zero);
            }
            for (int i=0; i<digitList.decimalAt; ++i) {
                result.append((i < digitList.count) ?
                          (char)(digitList.digits[i] + zeroDelta) : zero);
            }
            delegate.formatted(Field.EXPONENT, Field.EXPONENT, eFieldStart,
                               result.length(), result);
        } else {
            int iFieldStart = result.length();

            // Output the integer portion.  Here 'count' is the total
            // number of integer digits we will display, including both
            // leading zeros required to satisfy getMinimumIntegerDigits,
            // and actual digits present in the number.
            int count = minIntDigits;
            int digitIndex = 0; // Index into digitList.fDigits[]
            if (digitList.decimalAt > 0 && count < digitList.decimalAt) {
                count = digitList.decimalAt;
            }

            // Handle the case where getMaximumIntegerDigits() is smaller
            // than the real number of integer digits.  If this is so, we
            // output the least significant max integer digits.  For example,
            // the value 1997 printed with 2 max integer digits is just "97".
            if (count > maxIntDigits) {
                count = maxIntDigits;
                digitIndex = digitList.decimalAt - count;
            }

            int sizeBeforeIntegerPart = result.length();
            for (int i=count-1; i>=0; --i) {
                if (i < digitList.decimalAt && digitIndex < digitList.count) {
                    // Output a real digit
                    result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
                } else {
                    // Output a leading zero
                    result.append(zero);
                }

                // Output grouping separator if necessary.  Don't output a
                // grouping separator if i==0 though; that's at the end of
                // the integer part.
                if (isGroupingUsed() && i>0 && (groupingSize != 0) &&
                    (i % groupingSize == 0)) {
                    int gStart = result.length();
                    result.append(grouping);
                    delegate.formatted(Field.GROUPING_SEPARATOR,
                                       Field.GROUPING_SEPARATOR, gStart,
                                       result.length(), result);
                }
            }

            // Determine whether or not there are any printable fractional
            // digits.  If we've used up the digits we know there aren't.
            boolean fractionPresent = (minFraDigits > 0) ||
                (!isInteger && digitIndex < digitList.count);

            // If there is no fraction present, and we haven't printed any
            // integer digits, then print a zero.  Otherwise we won't print
            // _any_ digits, and we won't be able to parse this string.
            if (!fractionPresent && result.length() == sizeBeforeIntegerPart) {
                result.append(zero);
            }

            delegate.formatted(INTEGER_FIELD, Field.INTEGER, Field.INTEGER,
                               iFieldStart, result.length(), result);

            // Output the decimal separator if we always do so.
            int sStart = result.length();
            if (decimalSeparatorAlwaysShown || fractionPresent) {
                result.append(decimal);
            }

            if (sStart != result.length()) {
                delegate.formatted(Field.DECIMAL_SEPARATOR,
                                   Field.DECIMAL_SEPARATOR,
                                   sStart, result.length(), result);
            }
            int fFieldStart = result.length();

            for (int i=0; i < maxFraDigits; ++i) {
                // Here is where we escape from the loop.  We escape if we've
                // output the maximum fraction digits (specified in the for
                // expression above).
                // We also stop when we've output the minimum digits and either:
                // we have an integer, so there is no fractional stuff to
                // display, or we're out of significant digits.
                if (i >= minFraDigits &&
                    (isInteger || digitIndex >= digitList.count)) {
                    break;
                }

                // Output leading fractional zeros. These are zeros that come
                // after the decimal but before any significant digits. These
                // are only output if abs(number being formatted) < 1.0.
                if (-1-i > (digitList.decimalAt-1)) {
                    result.append(zero);
                    continue;
                }

                // Output a digit, if we have any precision left, or a
                // zero if we don't.  We don't want to output noise digits.
                if (!isInteger && digitIndex < digitList.count) {
                    result.append((char)(digitList.digits[digitIndex++] + zeroDelta));
                } else {
                    result.append(zero);
                }
            }

            // Record field information for caller.
            delegate.formatted(FRACTION_FIELD, Field.FRACTION, Field.FRACTION,
                               fFieldStart, result.length(), result);
        }

        if (isNegative) {
            append(result, negativeSuffix, delegate,
                   getNegativeSuffixFieldPositions(), Field.SIGN);
        }
        else {
            append(result, positiveSuffix, delegate,
                   getPositiveSuffixFieldPositions(), Field.SIGN);
        }

        return result;
    }
0
3
分享到:
评论

相关推荐

    Android计算器 源码

    【Android计算器 源码】是一个适合初学者深入理解Android应用开发的项目,它涵盖了基本的用户界面构建、事件处理以及简单的算法实现。这个计算器应用实现了基础的数学运算,包括加、减、乘、除,可能还包含了括号...

    android简单计算器源码

    这个“android简单计算器源码”提供了一个很好的起点,让我们来深入探讨其中涉及的关键知识点。 首先,我们关注的是**用户界面(UI)设计**。在Android中,我们通常使用XML布局文件来定义UI组件,如按钮和文本...

    一个简单的java计算器源码

    Java计算器源码是一个基础但重要的编程实践,它可以帮助初学者理解面向对象编程的基本概念和控制流程。...通过阅读和理解`JiSuanQi.java`的源码,开发者可以巩固对Java语言的理解,并逐步提升编程能力。

    java实现简单计算器源码

    结果显示时,我们可能希望保留一定的小数位数,可以使用`DecimalFormat`类来格式化输出结果。 9. **主函数与主类**: 所有的组件和逻辑都将被包含在一个主类中,通常命名为`Calculator`。主函数`main(String[] ...

    简单的java计算器源码

    ### Java简单计算器源码解析 #### 一、项目概述 本项目是一款基于Java Swing的简易计算器应用程序。通过分析所提供的部分代码片段,我们可以了解到该计算器具备基本的数学运算功能(如加、减、乘、除等),同时...

    CalculatorFrame.rar_源码

    这个计算器应用可能是一个简单的命令行界面或者图形用户界面(GUI)计算器,用于执行基本的算术运算,如加、减、乘、除。 在Java编程中,创建一个计算器通常会涉及到以下几个关键知识点: 1. **面向对象编程**:...

    数字格式化工具类

    下面是一个简单的`DecimalFormat`示例: ```java DecimalFormat df = new DecimalFormat("0.00"); String formatted = df.format(3.14159); System.out.println(formatted); // 输出 "3.14" ``` 标签中的“源码”...

    我找过来的计算器源程序

    根据提供的文件信息,我们可以分析出这是一段Java代码,用于创建一个简单的图形界面计算器应用程序。接下来,我们将深入探讨这段代码中的各个部分,并提取出相关的IT知识点。 ### 1. 导入必要的包 首先,代码导入...

    myeclipse注册机源码

    - **格式化输出**:使用`DecimalFormat`对数字进行格式化,例如`"000"`格式表示输出三位数,不足部分以0填充。 - **字符串转换**:将字符串转换为字符数组进行逐字符处理,再将字符数组转换回字符串形式。 #### ...

    关于java的四舍五入问题

    在Java编程语言中,处理数字的四舍五入操作是一项常见的任务,特别是在计算、财务或者数据分析...`Arith.java`文件可能包含了这些方法中的一个或多个实现,通过深入分析源码,我们可以了解其具体的实现逻辑和适用场景。

    基于Android系统的校园助手应用程序开发.zip

    Android提供了各种计算相关的类,如DecimalFormat用于格式化数字显示,以及Button和TextView控件用于交互和结果显示。 5. **小程序模块**:此应用中的“小应用”可能包括一些实用工具,如单位转换、日期时间计算等...

    Android记账源代码

    7. **日期和货币处理**:记账应用会涉及到日期和金额的处理,源代码可能会使用Java的`java.util.Date`或`java.time`包,以及`java.text.DecimalFormat`来进行格式化。 8. **权限管理**:如果应用需要访问用户的财务...

    java金额、java生成pdf、java编译资源文件

    以下是一个简单的iText示例,用于创建一个包含文本的PDF: ```java Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream("output.pdf")); document.open(); document.add...

    cal_java_

    可以使用DecimalFormat类来实现。 7. **控制流程**:为了处理复杂的运算,如括号内的表达式,可能需要用到栈(Stack)数据结构来实现运算符的优先级处理。 8. **程序设计模式**:虽然这是一个简单的应用,但仍然...

    java数字转金额(任意金额、支持负数、前缀0)

    这个过程涉及到将数字转换成符合人类阅读习惯的货币格式,包括添加逗号分隔符,处理负数,以及在必要时添加前导零。本文将深入探讨如何实现这一功能,并结合标签"源码"和"工具",给出一个实用的解决方案。 首先,...

    Java_Calculator_Source_Code.rar_java计算器代码

    Java计算器源码是一个典型的编程项目,它展示了如何在Java中实现一个简单的图形用户界面(GUI)应用程序。这个项目可能是为了帮助学生理解面向对象编程、事件处理以及GUI设计的基础知识。以下将详细介绍Java计算器的...

    JAVA编写的计算器

    - **控制台输入/输出**:简单的实现可以基于控制台,使用`Scanner`类获取用户输入,并通过`System.out.println()`显示结果。 - **图形用户界面(GUI)**:更高级的应用可能使用Java的Swing或JavaFX库创建图形界面...

    Java i18n的简单实现

    `java.text.SimpleDateFormat`和`java.text.DecimalFormat`类可以实现这一功能。例如,我们可以根据用户所在的地区来设置日期格式: ```java SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日", Locale...

    Java语言程序设计

    本书不仅能使读者掌握Java语言,而且能够让读者对现实世界中较简单的问题及其解决方法用计算机语言进行描述。 本书既可供大专院校用作“Java语言程序设计”课程教材,也可供Java 爱好者作为入门的自学教材。 目录第...

Global site tag (gtag.js) - Google Analytics