Java Double Number Format formatDoubleFast(double source, int decimals, int precision, StringBuffer target)

Here you can find the source of formatDoubleFast(double source, int decimals, int precision, StringBuffer target)

Description

Rounds the given source value at the given precision and writes the rounded value into the given target

This method internally uses double precision computation and rounding, so the result may not be accurate (see formatDouble method for conditions).

License

Apache License

Parameter

Parameter Description
source the source value to round
decimals the decimals to round at (use if abs(source) ≥ 1.0)
precision the precision to round at (use if abs(source) < 1.0)
target the buffer to write to

Declaration

public static void formatDoubleFast(double source, int decimals, int precision, StringBuffer target) 

Method Source Code

//package com.java2s;
/*//from   w ww  .  ja v  a  2  s  . c  o  m
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

public class Main {
    private static final double[] POWERS_OF_TEN_DOUBLE = new double[30];

    /**
     * Rounds the given source value at the given precision
     * and writes the rounded value into the given target
     * <p>
     * This method internally uses double precision computation and rounding,
     * so the result may not be accurate (see formatDouble method for conditions).
     *
     * @param source the source value to round
     * @param decimals the decimals to round at (use if abs(source) &ge; 1.0)
     * @param precision the precision to round at (use if abs(source) &lt; 1.0)
     * @param target the buffer to write to
     */
    public static void formatDoubleFast(double source, int decimals, int precision, StringBuffer target) {
        if (isRoundedToZero(source, decimals, precision)) {
            // Will always be rounded to 0
            target.append('0');
            return;
        } else if (Double.isNaN(source) || Double.isInfinite(source)) {
            // Cannot be formated
            target.append(Double.toString(source));
            return;
        }

        boolean isPositive = source >= 0.0;
        source = Math.abs(source);
        int scale = (source >= 1.0) ? decimals : precision;

        long intPart = (long) Math.floor(source);
        double tenScale = tenPowDouble(scale);
        double fracUnroundedPart = (source - intPart) * tenScale;
        long fracPart = Math.round(fracUnroundedPart);
        if (fracPart >= tenScale) {
            intPart++;
            fracPart = Math.round(fracPart - tenScale);
        }
        if (fracPart != 0L) {
            // Remove trailing zeroes
            while (fracPart % 10L == 0L) {
                fracPart = fracPart / 10L;
                scale--;
            }
        }

        if (intPart != 0L || fracPart != 0L) {
            // non-zero value
            if (!isPositive) {
                // negative value, insert sign
                target.append('-');
            }
            // append integer part
            target.append(intPart);
            if (fracPart != 0L) {
                // append fractional part
                target.append('.');
                // insert leading zeroes
                while (scale > 0 && fracPart < tenPowDouble(--scale)) {
                    target.append('0');
                }
                target.append(fracPart);
            }
        } else {
            target.append('0');
        }
    }

    /**
     * Returns true if the given source value will be rounded to zero
     *
     * @param source the source value to round
     * @param decimals the decimals to round at (use if abs(source) &ge; 1.0)
     * @param precision the precision to round at (use if abs(source) &lt; 1.0)
     * @return true if the source value will be rounded to zero
     */
    private static boolean isRoundedToZero(double source, int decimals, int precision) {
        // Use 4.999999999999999 instead of 5 since in some cases, 5.0 / 1eN > 5e-N (e.g. for N = 37, 42, 45, 66, ...)
        return source == 0.0
                || Math.abs(source) < 4.999999999999999 / tenPowDouble(Math.max(decimals, precision) + 1);
    }

    private static double tenPowDouble(int n) {
        assert n >= 0;
        return n < POWERS_OF_TEN_DOUBLE.length ? POWERS_OF_TEN_DOUBLE[n] : Math.pow(10, n);
    }
}

Related

  1. formatDouble(double value, int decimals)
  2. formatDouble(final double value)
  3. formatDouble(final Object value)
  4. formatDouble(String value)
  5. formatDoubleAsString(double num, int n)
  6. formatDoubleForDecimalPlaces(double d, int decimalcount)
  7. formatDoubleInfinity(Double d)
  8. formatDoublePrecise(double source, int decimals, int precision, StringBuffer target)
  9. formatDoubleToFixedLength(String value, int length)