package medusa.georgios.enhanced_mcl;
import java.util.Arrays;

/**
 * DoubleFormat formats double numbers into a specified digit format. The
 * difference to NumberFormat and DecimalFormat is that this DigitFormat is
 * based on a strategy to focus on a given number of nonzero digits, for which
 * it rounds numbers if necessary. In addition, it is possible to format a
 * number into a String that has a specified length, with a strategy to first
 * obey the significant-digit rule and then try to either space-pad the string
 * on the left or shorten the string by rounding, converting to
 * mantissa-exponent format or indicating overflow or underflow. Although the
 * class does not yield separator-aligned numbers, it yields a readable output.
 * 
 * @author heinrich
 */
public class DoubleFormat {

    /**
     * Format the number x with n significant digits.
     * 
     * @param x
     * @param ndigits
     * @return
     */
    public static double format(double x, int ndigits) {
        int magnitude = ExpDouble.orderOfMagnitude(x);
        double factor = Math.pow(10, ndigits - 1 - magnitude);
        double y = Math.round(x * factor) / factor;

        return y;
    }

    /**
     * Format the number so it becomes exactly as large as the argument strlen.
     * The number of nonzero digits is tried to be ndigits. If strlen does not
     * have enough space for this, this number is reduced or the formatting
     * switched to exponential notation (in that priority order). If this is not
     * successful, null is returned;
     * 

* TODO: debug so that lengths < 5 can be allowed * * TODO: debug conditions for exponential notation * * TODO: debug truncation for mixed numbers * * @param x the number to be formatted. * @param ndigits the maximum number of significant (non-zero) digits * @param strlen the exact number of characters in the string returned * (positive for right-aligned, negative for left-aligned) * @return the formatted number string or null */ static String format(double x, int ndigits, int strlen) { String s = null; boolean leftalign = false; if (strlen < 0) { strlen = -strlen; leftalign = true; } if (strlen < 5) throw new IllegalArgumentException("Cannot use yet abs(strlen) < 5"); int pad = 0; ExpDouble d = new ExpDouble(x, ndigits); int len = d.strlen(); pad = strlen - len; if (pad >= 0) { s = d.toString(); } else { // if it has a fraction, it can be right-trucated if (d.exponent < 0) { // retry rounding if at least one digit can be displayed as // 0.00# int newdigits = d.digits - -pad; // at least one digit necessary if (newdigits > 0) { boolean plusone = d.round(newdigits); // if rounding up to next order of magnitude if (plusone && newdigits > 1) { d.round(newdigits - 1); } else { s = exponentialNotation(d, strlen); } s = d.toString(); } else { s = exponentialNotation(d, strlen); } } else { // try exponential notation (1.2E3) s = exponentialNotation(d, strlen); } pad = strlen - s.length(); } String spc = space(pad); if (leftalign) { return s + spc; } else { return spc + s; } } /** * @param d expdouble object * @param strlen maximum string length * @return number as string in exponential notation */ private static String exponentialNotation(ExpDouble d, int strlen) { String s; int len; len = d.strlenexp(); int minlen = d.minstrlenexp(); if (minlen > strlen) { char[] cc = new char[strlen]; if (d.exponent >= 0) { Arrays.fill(cc, '>'); } else { Arrays.fill(cc, '<'); } s = new String(cc); } // do all digits fit? int diff = strlen - len; if (diff == -1) { // at least two digits (with additional point d.round(d.digits + diff); } else { // only one digit (this yields minlen) d.round(1); } s = d.toExpString(); return s; } private static String space(int pad) { char[] ch = new char[pad]; Arrays.fill(ch, ' '); String spc = new String(ch); return spc; } }

Ads help maintain this website.