/** * Copyright (c) 2005 - Bob Lang (http://www.cems.uwe.ac.uk/~lrlang/) * * http://www.frinika.com * * This file is part of Frinika. * * Frinika is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * Frinika is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with Frinika; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.frinika.contrib.boblang; //package uwejava; /** Text conversion and formatting methods. Each method is static. <p>The methods are divided into two groups:<ul> <li>Methods where numeric values are converted and formatted into strings</li> <li>Methods where a string converted into a numeric value</li> </ul></p> <p>Methods for converting and formatting values into strings are:<ul> <li>Real formatting:<ul> <li>doubleToString (double d, int width, int decimal)</li> <li>floatToString (float f, int width, int decimal)</li> </ul> <p>where:<ul> <li>width = total field width in characters<br> (Minimum allowed width is 4)</li> <li>decimal = number of digits after decimal point<br> (uses exponential notation if decimal is -ve)</li> <p>If the number is too large to print in ddd.dd format, it will be output in exponential form.</p> <p>If the total field width is too small, then the width is automatically increased</p> </ul> <li>Integer formatting:<ul> <li>longToString (long l, int width)</li> <li>intToString (int i, int width)</li> <li>shortToString (short s, int width)</li> </ul> <p>where: <ul> <li>width = total field width in characters<br> +ve width - use leading spaces<br> -ve width - use leading zeroes<br> <p>If the total field width is too small, then the width is automatically increased. To format a value in the minimum number of characters, use a width of +1.</p></li> </ul> </ul> <p>Methods for converting strings to values are:<ul> <li>Validity checks:<ul> <li>boolean isValidDouble (String s)</li> <li>boolean isValidFloat (String s)</li> <li>boolean isValidLong (String s)</li> <li>boolean isValidInt (String s)</li> <li>boolean isValidShort (String s)</li> </ul></li> <li>Conversion methods:<ul> <li>double StringToDouble (String s, double defaultValue)</li> <li>float StringToFloat (String s, float defaultValue)</li> <li>long StringToLong (String s, long defaultValue)</li> <li>int StringToInt (String s, int defaultValue)</li> <li>short StringToShort (String s, short defaultValue)</li> </ul> <p>where:<ul> <li>defaultValue - value returned if the string is invalid</li> </ul> </ul></li> </ul></p> @author Bob Lang @version Thu Nov 15 2001 @see TextInput @see TextOutput */ public class Convert { // ... PRIVATE DECLARATIONS ... // Version for this class private static final String VERSION_STRING = "uwejava.Convert version dated Thu Nov 15 2001"; // Conversion table for integer strings private static final char [] DIGIT_CHAR = {'0','1','2','3','4','5','6','7','8','9',' ','-'}; private static final int MARK_LEAD_SPACE = 10; private static final int MARK_MINUS = 11; // Standard width specifications private static final int MAX_WIDTH = 24; //Max numeric width private static final int MIN_EXP_WIDTH = 10; //Min width for exp format private static final int MIN_DECIMAL_WIDTH = 4; //Min width for dd.dd form private static final int DOUBLE_EXP_WIDTH = 3; //double numbers use e+ddd private static final int FLOAT_EXP_WIDTH = 2; //float numbers use e+dd // Largest number that can be printed in the form ddddd.dddd private static final double MAX_DECIMAL_VALUE = 9e18; //From long type private static final int MAX_DECIMAL_DIGITS = 18; // Power lookup table to avoid calling the Math library private static double [] powerTable = {1.0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29}; // ... PRIVATE METHODS ... // Convert a double real value to exponent string in form dd.dddde+ddd private static String convDoubleExp (double d, int width, int decimal, int exp) { String buffer; // Build up output representation boolean negative; // Processing a negative number int extraChars = 4; // Sign, ".", "e" and Exponent sign int powerOfTen = 0; // Printed exponent part int pre; // Number of digits before decimal point double minNorm, maxNorm; // Used to put 1..9 in first digit position double round; // Used for rounding last sig digit long preDigits; // Int value of normalised value long postDigits; // Int value of digits after decimal point // Can't handle negative numbers too well negative = d < 0.0; d = Math.abs (d); // Check the input formatting specifications // The exponent width is limited to 2 or 3 characters if (exp < 2) { exp = 2; } if (exp > 3) { exp = 3; } // Check the width and possibly adjust decimal if (width < MIN_EXP_WIDTH) { decimal = decimal + MIN_EXP_WIDTH - width; width = MIN_EXP_WIDTH; } //if if (width > MAX_WIDTH) { decimal = decimal - MAX_WIDTH + width; width = MAX_WIDTH; } //if // Check the number of decimal digits if (decimal > width - exp - extraChars - 1) { decimal = width - exp - extraChars - 1; } //if if (decimal <= 0) { decimal = 0; extraChars = 3; // No decimal point so one less extra char } //if // Can't have more than 18 digits before decimal point pre = width - decimal - exp - extraChars; if (pre >= MAX_DECIMAL_VALUE) { pre = MAX_DECIMAL_DIGITS; } //if // Normalise the number so 1..9 will appear as first printed digit maxNorm = powerTable [pre]; minNorm = maxNorm / 10.0; // Perform normalisation and calculate power of ten to go after 'e' while (d > maxNorm) { d = d / 10.0; powerOfTen++; } // while while (d < minNorm) { d = d * 10.0; powerOfTen--; } // while // Round up or down the decimal digits and re-normalise round = 0.5 / powerTable [decimal]; d = d + round; while (d > maxNorm) { d = d / 10.0; powerOfTen++; } // while // Get two long numbers representing numbers before and after decimal. preDigits = (long) d; // Lose the decimal part postDigits = (long) ((d-preDigits) * powerTable [decimal]); // Build up the string buffer if (negative) { buffer = "-"; } else { buffer = " "; } //if buffer = buffer + convLongLS (preDigits, pre); if (decimal != 0) { buffer += '.'; buffer += convLongLZ (postDigits, decimal); } //if if (powerOfTen < 0) { buffer += "e-"; powerOfTen = -powerOfTen; } else { buffer += "e+"; } //if buffer += convLongLZ (powerOfTen, exp); // Return the final result return buffer; } // convDoubleExp () // Convert a double real value to string in form dddd.dd private static String convDouble (double d, int width, int decimal) { String buffer; // Build up output representation boolean negative; // Processing a negative number int pre; // Number of digits before decimal point double round; // Used for rounding last sig digit long preDigits; // Int value of normalised value long postDigits; // Int value of digits after decimal point // Can't handle negative numbers too well negative = d < 0.0; d = Math.abs (d); // Check the input formatting specifications // Check the number of decimal digits if (decimal > width - 1) { decimal = width - 1; } //if if (decimal <= 0) { decimal = 0; } //if // Check the width and possibly adjust decimal if (width < MIN_DECIMAL_WIDTH) { //decimal = decimal + MIN_DECIMAL_WIDTH - width; width = MIN_DECIMAL_WIDTH; } //if if (width > MAX_WIDTH) { decimal = decimal - MAX_WIDTH + width; width = MAX_WIDTH; } //if // Calculate number of digits before decimal point pre = width - decimal - 1; if (decimal == 0) { pre++; //No decimal point so we'll get an extra digit } //if // Round up or down the decimal digits round = 0.5 / powerTable [decimal]; d = d + round; // Get two long numbers representing numbers before and after decimal. preDigits = (long) d; // Lose the decimal part postDigits = (long) ((d-preDigits) * powerTable [decimal]); // Build up the string buffer if (negative) { preDigits = -preDigits; } //if buffer = convLongLS (preDigits, pre); if (decimal != 0) { buffer += '.'; buffer += convLongLZ (postDigits, decimal); } //if // Return the final result return buffer; } // convDouble () // Convert a long integer to a string (with leading spaces) private static String convLongLS (long l, int width) { String buffer; // Build up output representation boolean negative; // Processing a negative number long [] digits = // Digits discovered by successive mod 10 new long [MAX_WIDTH]; int i; // Loop counter int digitValue; // Value of each digit to be converted // Can't handle negative numbers negative = l < 0; if (negative) { l = -l; } //if // Check the input formatting specifications if (width > MAX_WIDTH) { width = MAX_WIDTH; } //if // Fill the digit array with marker values for (i=0; i<MAX_WIDTH; i++) { digits [i] = MARK_LEAD_SPACE; } // for // Extract the digits from the long number i = 0; digits [i] = l % 10; while (l > 0) { digits [i] = l % 10; l = l / 10; i++; } //while // Mark the sign position if (negative) { digits [i] = MARK_MINUS; i++; } // Catch the correct number of leading zeroes if (width > i) { i = width; } //if // Build up the return string buffer = ""; i--; while (i >= 0) { digitValue = (int) digits [i]; buffer += DIGIT_CHAR [digitValue]; i--; } // while // Return final result return buffer; } // convLongLS () // Convert a long integer to a string (with leading zeroes) private static String convLongLZ (long l, int width) { String buffer; // Build up output representation boolean negative; // Processing a negative number long [] digits = // Digits discovered by successive mod 10 new long [MAX_WIDTH]; int i; // Loop counter int digitValue; // Value of each digit to be converted //Create an empty buffer buffer = ""; // Can't handle negative numbers negative = l < 0; if (negative) { //Convert the number to positive l = Math.abs (l); //Put the sign in the buffer and reduce width by one to compensate buffer = "-"; width--; //Doesn't matter if this goes to 0 or -ve } //if // Check the input formatting specifications if (width > MAX_WIDTH) { width = MAX_WIDTH; } //if // Fill the digit array with leading zeroes for (i=0; i<MAX_WIDTH; i++) { digits [i] = 0; } // for // Extract the digits from the long number i = 0; digits [i] = l % 10; while (l > 0) { digits [i] = l % 10; l = l / 10; i++; } //while // Catch the correct number of leading zeroes if (width > i) { i = width; } //if // Build up the return string i--; while (i >= 0) { digitValue = (int) digits [i]; buffer += DIGIT_CHAR [digitValue]; i--; } // while // Return final result return buffer; } // convLongLZ () // ... DUMMY CONSTRUCTOR FOR JAVADOC PURPOSES ... /** This class only contains <code>static</code> methods. There is no need to call its constructor. */ public Convert () { // Do nothing } // Convert () // ... PUBLIC STATIC CONVERSION ROUTINES ... /** Return the version of this class as a String */ public static String version () { return VERSION_STRING; } // version () /** Convert a double to a string. See documentation at start of class for parameter usage. <P>Example call:</P> <P><CODE>String s = Convert.doubleToString (doubleValue, width, decimal); </CODE></P> */ public static String doubleToString (double d, int width, int decimal) { if (decimal<0 || (Math.abs (d) > MAX_DECIMAL_VALUE)) { return convDoubleExp (d, width, Math.abs (decimal), DOUBLE_EXP_WIDTH); } else { return convDouble (d, width, decimal); } //if } // doubleToString () /** Convert a float to a string. See documentation at start of class for parameter usage. <P>Example call:</P> <P><CODE>String s = Convert.floatToString (floatValue, width, decimal); </CODE></P> */ public static String floatToString (float f, int width, int decimal) { if (decimal<0 || (Math.abs (f) > MAX_DECIMAL_VALUE)) { return convDoubleExp (f, width, Math.abs (decimal), FLOAT_EXP_WIDTH); } else { return convDouble (f, width, decimal); } //if } // floatToString () /** Convert a long integer to a string. See documentation at start of class for parameter usage. <P>Example call:</P> <P><CODE>String s = Convert.longToString (longValue, width); </CODE></P> */ public static String longToString (long l, int width) { if (width < 0) { return convLongLZ (l, Math.abs (width)); } else { return convLongLS (l, width); } //if } // longToString () /** Convert a standard integer to a string. See documentation at start of class for parameter usage. <P>Example call:</P> <P><CODE>String s = Convert.intToString (intValue, width); </CODE></P> */ public static String intToString (int i, int width) { if (width < 0) { return convLongLZ (i, Math.abs (width)); } else { return convLongLS (i, width); } //if } // intToString () /** Convert a short integer to a string. See documentation at start of class for parameter usage. <P>Example call:</P> <P><CODE>String s = Convert.shortToString (shortValue, width); </CODE></P> */ public static String shortToString (short s, int width) { if (width < 0) { return convLongLZ (s, Math.abs (width)); } else { return convLongLS (s, width); } //if } // shortToString () /** Test if the characters in a string may be converted into a double value. <P>Example call:</P> <P><CODE>boolean b = Convert.isValidDouble (digitString); </CODE></P> */ public static boolean isValidDouble (String s) { // Declare variables Double d; boolean valid = false; // Try to format the string try { s = s.trim (); d = new Double (s); valid = true; } // try // Exception handler catch (NumberFormatException e) { valid = false; } // catch // Return the result //finally { return valid; //} // finally } // isValidDouble () /** Convert a string to a double. If the string is not a valid double value then the default value is returned. The string may be checked for validity by calling isValidDouble () <P>Example call:</P> <P><CODE>double val = Convert.stringToDouble (digitString, defaultValue); </CODE></P> */ public static double stringToDouble (String s, double defaultValue) { // Declare variables Double d; double result = defaultValue; // Try to format the string try { s = s.trim (); d = new Double (s); result = d.doubleValue (); } // try // Exception handler catch (NumberFormatException e) { result = defaultValue; } // catch // Return the result //finally { return result; //} // finally } // StringToDouble () /** Test if the characters in a string may be converted into a float value. <P>Example call:</P> <P><CODE>boolean b = Convert.isValidFloat (digitString); </CODE></P> */ public static boolean isValidFloat (String s) { // Declare variables Float d; boolean valid = false; // Try to format the string try { s = s.trim (); d = new Float (s); valid = true; } // try // Exception handler catch (NumberFormatException e) { valid = false; } // catch // Return the result //finally { return valid; //} // finally } // isValidFloat () /** Convert a string to a float. If the string is not a valid float value then the default value is returned. The string may be checked for validity by calling isValidFloat () <P>Example call:</P> <P><CODE>float val = Convert.stringToFloat (digitString, (float) defaultValue); </CODE></P> */ public static float stringToFloat (String s, float defaultValue) { // Declare variables Float d; float result = defaultValue; // Try to format the string try { s = s.trim (); d = new Float (s); result = d.floatValue (); } // try // Exception handler catch (NumberFormatException e) { result = defaultValue; } // catch // Return the result //finally { return result; //} // finally } // StringToFloat () /** Test if the characters in a string may be converted into a long integer. <P>Example call:</P> <P><CODE>boolean b = Convert.isValidLong (digitString); </CODE></P> */ public static boolean isValidLong (String s) { // Declare variables Long d; boolean valid = false; // Try to format the string try { s = s.trim (); d = new Long (s); valid = true; } // try // Exception handler catch (NumberFormatException e) { valid = false; } // catch // Return the result //finally { return valid; //} // finally } // isValidLong () /** Convert a string to a long. If the string is not a valid long value then the default value is returned. The string may be checked for validity by calling isValidLong () <P>Example call:</P> <P><CODE>long val = Convert.stringToLong (digitString, (long) defaultValue); </CODE></P> */ public static long stringToLong (String s, long defaultValue) { // Declare variables Long d; long result = defaultValue; // Try to format the string try { s = s.trim (); d = new Long (s); result = d.longValue (); } // try // Exception handler catch (NumberFormatException e) { result = defaultValue; } // catch // Return the result //finally { return result; //} // finally } // StringToLong () /** Test if the characters in a string may be converted into an integer. <P>Example call:</P> <P><CODE>boolean b = Convert.isValidInt (digitString); </CODE></P> */ public static boolean isValidInt (String s) { // Declare variables Integer d; boolean valid = false; // Try to format the string try { s = s.trim (); d = new Integer (s); valid = true; } // try // Exception handler catch (NumberFormatException e) { valid = false; } // catch // Return the result //finally { return valid; //} // finally } // isValidInt () /** Convert a string to a int. If the string is not a valid int value then the default value is returned. The string may be checked for validity by calling isValidInt () <P>Example call:</P> <P><CODE>int val = Convert.stringToInt (digitString, defaultValue); </CODE></P> */ public static int stringToInt (String s, int defaultValue) { // Declare variables Integer d; int result = defaultValue; // Try to format the string try { s = s.trim (); d = new Integer (s); result = d.intValue (); } // try // Exception handler catch (NumberFormatException e) { result = defaultValue; } // catch // Return the result //finally { return result; //} // finally } // StringToInt () /** Test if the characters in a string may be converted into a short integer. <P>Example call:</P> <P><CODE>boolean b = Convert.isValidShort (digitString); </CODE></P> */ public static boolean isValidShort (String s) { // Declare variables Short d; boolean valid = false; // Try to format the string try { s = s.trim (); d = new Short (s); valid = true; } // try // Exception handler catch (NumberFormatException e) { valid = false; } // catch // Return the result //finally { return valid; //} // finally } // isValidShort () /** Convert a string to a short. If the string is not a valid short value then the default value is returned. The string may be checked for validity by calling isValidShort () <P>Example call:</P> <P><CODE>short val = Convert.stringToShort (digitString, (short) defaultValue); </CODE></P> */ public static short stringToShort (String s, short defaultValue) { // Declare variables Short d; short result = defaultValue; // Try to format the string try { s = s.trim (); d = new Short (s); result = d.shortValue (); } // try // Exception handler catch (NumberFormatException e) { result = defaultValue; } // catch // Return the result //finally { return result; //} // finally } // StringToShort () } //Convert