ucar.unidata.util.Format Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
* See LICENSE for license information.
*/
package ucar.unidata.util;
import java.util.Formatter;
/**
* static formatting utilities. Replace with standard java library when possible.
*
* @author John Caron
*/
public class Format {
/**
* Blank fill sbuff with blanks, until position tabStop.
*
* @param sbuff StringBuffer to manipulate
* @param tabStop pad out to here
* @param alwaysOne true if you want to guarentee at least one space.
*/
public static void tab(StringBuffer sbuff, int tabStop, boolean alwaysOne) {
int len = sbuff.length();
if (tabStop > len) {
sbuff.setLength(tabStop);
for (int i = len; i < tabStop; i++) {
sbuff.setCharAt(i, ' ');
}
} else if (alwaysOne) {
sbuff.setLength(len + 1);
sbuff.setCharAt(len, ' ');
}
}
/**
* Blank fill sbuff with blanks, until position tabStop.
*
* @param sbuff StringBuilder to manipulate
* @param tabStop pad out to here
* @param alwaysOne true if you want to guarentee at least one space.
*/
public static void tab(StringBuilder sbuff, int tabStop, boolean alwaysOne) {
int len = sbuff.length();
if (tabStop > len) {
sbuff.setLength(tabStop);
for (int i = len; i < tabStop; i++) {
sbuff.setCharAt(i, ' ');
}
} else if (alwaysOne) {
sbuff.setLength(len + 1);
sbuff.setCharAt(len, ' ');
}
}
/**
* Create a new string by padding the existing one with blanks to specified width.
* Do nothing if length is already greater or equal to width.
*
* @param s string to pad
* @param width length of return string
* @return padded string
*/
public static String s(String s, int width) {
return pad(s, width, false);
}
/**
* Create a new string by padding the existing one with blanks to specified width.
* Do nothing if length is already greater or equal to width.
*
* @param s string to pad
* @param width length of return string
* @param rightJustify if true, right justify, else left justify
* @return padded string
*/
public static String pad(String s, int width, boolean rightJustify) {
if (s.length() >= width) {
return s;
}
StringBuilder sbuff = new StringBuilder(width);
int need = width - s.length();
sbuff.setLength(need);
for (int i = 0; i < need; i++) {
sbuff.setCharAt(i, ' ');
}
if (rightJustify) {
sbuff.append(s);
} else {
sbuff.insert(0, s);
}
return sbuff.toString();
}
/**
* Format an integer value.
*
* @param v : value
* @param width pad to this width
* @return formatted string
*/
public static String i(int v, int width) {
return pad(Integer.toString(v), width, true);
}
/**
* Format a long value.
*
* @param v : value
* @param width pad to this width
* @return formatted string
*/
public static String l(long v, int width) {
return pad(Long.toString(v), width, true);
}
/**
* Double value formatting with minimum number of significant figures in a minimum width.
* This will try to do a reasonable job of getting
* a representation that has min_sigfig significant figures in minimum width.
*
* @param d the number to format.
* @param min_sigfig minimum number of significant figures
* @return string representation
*/
public static String d(double d, int min_sigfig) {
return formatDouble(d, min_sigfig, -1).trim();
}
/**
* Double value formatting with minimum number of significant figures in a specified width.
* This will try to do a reasonable job of getting
* a representation that has min_sigfig significant figures in the specified width.
* Right now, all it does is call d( double d, int min_sigfig) and left pad out to width chars.
*
* @param d the number to format.
* @param min_sigfig minimum number of significant figures
* @param width width of the result
* @return string representation, right justified in field of specified width
*/
public static String d(double d, int min_sigfig, int width) {
String s = Format.d(d, min_sigfig);
return pad(s, width, true);
}
/**
* Double value formatting with fixed number of digits to the right of the decimal point.
*
* @param d the number to format.
* @param fixed_decimals number of digits to the right of the decimal point
* @return string representation, with specified number of decimal places
*/
public static String dfrac(double d, int fixed_decimals) {
return formatDouble(d, 100, fixed_decimals).trim();
//String s = Double.toString( d);
//s = sigfigFix( s, 100, num_dec);
//return s.trim();
}
/* This dorks with Double.toString():
*
* From Double.toString() (m = magnitude of the number):
*
* If m is greater than or equal to 10^-3 but less than 10^7, then it is represented as the
* integer part of m, in decimal form with no leading zeroes, followed by '.' (.),
* followed by one or more decimal digits representing the fractional part of m.
*
* If m is less than 10^-3 or greater than 10^7, then it is represented in scientific notation.
* Let n be the unique integer such that 10n<=m<10n+1; then let a be the mathematically exact
* quotient of m and 10n so that 1<=a<10. The magnitude is then represented as the integer part
* of a, as a single decimal digit, followed by '.' (.), followed by decimal digits representing
* the fractional part of a, followed by the letter 'E' (E), followed by a representation of n
* as a decimal integer, as produced by the method Integer.toString(int).
*
* How many digits must be printed for the fractional part of m or a? There must be
* at least one digit to represent the fractional part, and beyond that as many,
* but only as many, more digits as are needed to uniquely distinguish the argument
* value from adjacent values of type double. That is, suppose that x is the exact
* mathematical value represented by the decimal representation produced by this method
* for a finite nonzero argument d. Then d must be the double value nearest to x; or if
* two double values are equally close to x, then d must be one of them and the least
* significant bit of the significand of d must be 0.
*/
/**
* Format a double value
*
* @param d value to format
* @param min_sigFigs minimum significant figures
* @param fixed_decimals number of fixed decimals
* @return double formatted as a string
*/
public static String formatDouble(double d, int min_sigFigs, int fixed_decimals) {
String s = Double.toString(d);
// extract the sign
String sign;
String unsigned;
if (s.startsWith("-") || s.startsWith("+")) {
sign = s.substring(0, 1);
unsigned = s.substring(1);
} else {
sign = "";
unsigned = s;
}
// deal with exponential notation
String mantissa;
String exponent;
int eInd = unsigned.indexOf('E');
if (eInd == -1) {
eInd = unsigned.indexOf('e');
}
if (eInd == -1) {
mantissa = unsigned;
exponent = "";
} else {
mantissa = unsigned.substring(0, eInd);
exponent = unsigned.substring(eInd);
}
// deal with decimal point
StringBuilder number, fraction;
int dotInd = mantissa.indexOf('.');
if (dotInd == -1) {
number = new StringBuilder(mantissa);
fraction = new StringBuilder("");
} else {
number = new StringBuilder(mantissa.substring(0, dotInd));
fraction = new StringBuilder(mantissa.substring(dotInd + 1));
}
// number of significant figures
int numFigs = number.length();
int fracFigs = fraction.length();
// can do either fixed_decimals or min_sigFigs
if (fixed_decimals != -1) {
if (fixed_decimals == 0) {
fraction.setLength(0);
} else if (fixed_decimals > fracFigs) {
int want = fixed_decimals - fracFigs;
for (int i = 0; i < want; i++) {
fraction.append("0");
}
} else if (fixed_decimals < fracFigs) {
int chop = fracFigs - fixed_decimals; // LOOK should round !!
fraction.setLength(fraction.length() - chop);
}
fracFigs = fixed_decimals;
} else {
// Don't count leading zeros in the fraction, if no number
if (((numFigs == 0) || number.toString().equals("0"))
&& (fracFigs > 0)) {
numFigs = 0;
number = new StringBuilder("");
for (int i = 0; i < fraction.length(); ++i) {
if (fraction.charAt(i) != '0') {
break;
}
--fracFigs;
}
}
// Don't count trailing zeroes in the number if no fraction
if ((fracFigs == 0) && (numFigs > 0)) {
for (int i = number.length() - 1; i > 0; i--) {
if (number.charAt(i) != '0') {
break;
}
--numFigs;
}
}
// deal with min sig figures
int sigFigs = numFigs + fracFigs;
if (sigFigs > min_sigFigs) {
// Want fewer figures in the fraction; chop (should round? )
int chop = Math.min(sigFigs - min_sigFigs, fracFigs);
fraction.setLength(fraction.length() - chop);
fracFigs -= chop;
}
}
/*int sigFigs = numFigs + fracFigs;
if (sigFigs > max_sigFigs) {
if (numFigs >= max_sigFigs) { // enough sig figs in just the number part
fraction.setLength( 0 );
for ( int i=max_sigFigs; i fracFigs) {
int want = dec_places - fracFigs;
for (int i=0; i 1.0e15) {
unit = "Pbytes";
size *= 1.0e-15;
} else if (size > 1.0e12) {
unit = "Tbytes";
size *= 1.0e-12;
} else if (size > 1.0e9) {
unit = "Gbytes";
size *= 1.0e-9;
} else if (size > 1.0e6) {
unit = "Mbytes";
size *= 1.0e-6;
} else if (size > 1.0e3) {
unit = "Kbytes";
size *= 1.0e-3;
} else {
unit = "bytes";
}
return Format.d(size, 4) + " " + unit;
}
//////////////////////////////////////////////////////////////////////////////////////
/**
* Show the value of a double to the significant figures
*
* @param d double value
* @param sigfig number of significant figures
*/
private static void show(double d, int sigfig) {
System.out.println("Format.d(" + d + "," + sigfig + ") == "
+ Format.d(d, sigfig));
}
/**
* Show the value of a double with specified number of decimal places
*
* @param d double value
* @param dec_places number of decimal places
*/
private static void show2(double d, int dec_places) {
System.out.println("Format.dfrac(" + d + "," + dec_places + ") == "
+ Format.dfrac(d, dec_places));
}
public static void doit(int scale, double n) {
Formatter f = new Formatter();
String format = "Prob_above_%f3." + scale;
f.format(format, n);
System.out.printf("%s %f == %s%n", format, n, f);
}
public static void main(String argv[]) {
doit(1, 1.00003);
System.out.printf("%f == %f3.1%n", 1.00003, 1.00003);
System.out.printf("%s%n", dfrac(1.00003, 0));
System.out.printf("%s%n", dfrac(1.00003, 1));
}
}