All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.xfa.ut.Numeric Maven / Gradle / Ivy

There is a newer version: 2024.11.18598.20241113T125352Z-241000
Show newest version
/*
 * ADOBE CONFIDENTIAL
 *
 * Copyright 2005 Adobe Systems Incorporated All Rights Reserved.
 *
 * NOTICE: All information contained herein is, and remains the property of
 * Adobe Systems Incorporated and its suppliers, if any. The intellectual and
 * technical concepts contained herein are proprietary to Adobe Systems
 * Incorporated and its suppliers and may be covered by U.S. and Foreign
 * Patents, patents in process, and are protected by trade secret or copyright
 * law. Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained from
 * Adobe Systems Incorporated.
 */
package com.adobe.xfa.ut;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.Locale;


/**
 *
 * @exclude from published api -- Mike Tardif, May 2006.
 */
public final class Numeric {

	private final static int MAX_PRECISION = 15;
	
	/*
	 * Disallow instances of this class.
	 */
	private Numeric() {
		// empty
	}

	private final static NumberFormat format;

	static {
		format = NumberFormat.getNumberInstance(Locale.US);
		format.setGroupingUsed(false);
		format.setMinimumIntegerDigits(1);
		format.setMaximumIntegerDigits(310);
	}

	//Bug#3018085: Define double to String conversion using BigDecimal
	/**
	 * Format a double as a string using BigDecimal
	 * @param dValue - the double value
	 * @param fracDigits - the number of fractional digits to render
	 * @return the formatted string
	 */
	public static String doubleToStringUsingBigDecimal(double dValue, int fracDigits, boolean bTruncate /* = false */) {
		if (Double.isNaN(dValue) || Double.isInfinite(dValue))
			return "";
		
		if (fracDigits >= 0) {
		
			if (fracDigits > MAX_PRECISION)
				fracDigits = MAX_PRECISION;
			
			double fraction = dValue - (int)dValue;
			int checkDigit = (int)(fraction * Math.pow(10.0, fracDigits + 1)) - (int)(fraction * Math.pow(10.0, fracDigits)) * 10;
			if (checkDigit == 5)
				dValue += Math.pow(0.1, fracDigits + 1);
			
			// Javaport: Java doesn't round when formatting, so we have to do it explicitly.
			// TODO: Minimize the use of Math.pow() 
			double p = Math.pow(10.0, fracDigits);					
			
			String conversionString = "%#." + fracDigits + "f";
			if (fracDigits == 0) conversionString = "%.0f";
			
			String sValue = String.format(conversionString, new BigDecimal(dValue));
			
			if (!bTruncate)
				return sValue;
			
			if (sValue.charAt(sValue.length() - 1) != '0')
				return sValue;
			
			int endIndex = sValue.length() - 1;
			while (sValue.charAt(endIndex) == '0')
				endIndex--;
			
			if (sValue.charAt(endIndex) == '.')
				endIndex--;
							
			return sValue.substring(0, endIndex + 1);
		}
		else {
			String sValue = getNumberFormat(fracDigits).format(dValue);
			return sValue;
		}
	}


	/**
	 * Format a double as a string
	 * @param dValue - the double value
	 * @param fracDigits - the number of fractional digits to render
	 * @return the formatted string
	 */
	public static String doubleToString(double dValue, int fracDigits, boolean bTruncate /* = false */) {
		if (Double.isNaN(dValue) || Double.isInfinite(dValue))
			return "";
		
		if (fracDigits >= 0) {
		
			if (fracDigits > MAX_PRECISION)
				fracDigits = MAX_PRECISION;
			
			double fraction = dValue - (int)dValue;
			int checkDigit = (int)(fraction * Math.pow(10.0, fracDigits + 1)) - (int)(fraction * Math.pow(10.0, fracDigits)) * 10;
			if (checkDigit == 5)
				dValue += Math.pow(0.1, fracDigits + 1);
			
			// Javaport: Java doesn't round when formatting, so we have to do it explicitly.
			// TODO: Minimize the use of Math.pow() 
			double p = Math.pow(10.0, fracDigits);					
			
			String conversionString = "%#." + fracDigits + "f";
			if (fracDigits == 0) conversionString = "%.0f";
			
			String sValue = String.format(conversionString, dValue);
			
			if (!bTruncate)
				return sValue;
			
			if (sValue.charAt(sValue.length() - 1) != '0')
				return sValue;
			
			int endIndex = sValue.length() - 1;
			while (sValue.charAt(endIndex) == '0')
				endIndex--;
			
			if (sValue.charAt(endIndex) == '.')
				endIndex--;
							
			return sValue.substring(0, endIndex + 1);
		}
		else {
			String sValue = getNumberFormat(fracDigits).format(dValue);
			return sValue;
		}
	}
	
	public static double stringToDouble(String str, boolean bAllowNaN /* = false */) {
		
		str = str.trim();
		
		if (str.length() == 0)
			return bAllowNaN ? Double.NaN : 0f;
		
		ParsePosition pp = new ParsePosition(0);
		// The number of fractional digits on the format used to parse is ignored.		
		Number n = getNumberFormat(1).parse(str, pp);		
		
		// Must not be errors and the entire input string must be consumed 
		if (n == null || pp.getErrorIndex() != -1 || pp.getIndex() < str.length()) {			
			return bAllowNaN ? Double.NaN : 0f;
		}
		
		double d = n.doubleValue();
		
		if (Double.isNaN(d) || Double.isInfinite(d)) {
			return bAllowNaN ? Double.NaN : 0f;
		}
			
		return d;
	}
	
	private static NumberFormat getNumberFormat(int fracDigits) {
		// Number format objects are not synchronized, so we can't
		// share instances across threads. To minimize the overhead
		// of creating a new instance each time we format a number,
		// keep a partially initialized instance that can be cloned 
		// each time it is used.
		NumberFormat customFormat = (NumberFormat)format.clone();
		customFormat.setMinimumFractionDigits(fracDigits);
		customFormat.setMaximumFractionDigits(fracDigits);
		return customFormat;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy