Here you can find the source of formatDoubleFast(double source, int decimals, int precision, StringBuffer target)
This method internally uses double precision computation and rounding, so the result may not be accurate (see formatDouble method for conditions).
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 |
public static void formatDoubleFast(double source, int decimals, int precision, StringBuffer target)
//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) ≥ 1.0) * @param precision the precision to round at (use if abs(source) < 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) ≥ 1.0) * @param precision the precision to round at (use if abs(source) < 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); } }