ScaledNumberFormatpublic class ScaledNumberFormat extends Format Format numbers scaled for human comprehension.
"Human-readable" output uses43 digits max, and puts unit suffixes at
the end. Makes output compact and easy-to-read esp. on huge disks.
Formatting code was originally in OpenBSD "df", converted to library routine.
Scanning code written by Ian Darwin, originally for OpenBSD libutil.
Rewritten in Java in January, 2001; re-synched with OpenBSD in 2004. |
Fields Summary |
---|
static final int | NONE | static final int | KILO | static final int | MEGA | static final int | GIGA | static final int | TERA | static final int | PETA | static final int | EXA | DecimalFormat | df | static char[] | scale_charsThe input scaling factors. All three arrays must be in same order. | int[] | unitsThe numeric scale values. All three arrays must be in same order. | static long[] | scale_factorsThe input scale sizes. All three arrays must be in same order. | private static final long | LLONG_MAX | static final int | MAX_DIGITS |
Constructors Summary |
---|
public ScaledNumberFormat()
df = new DecimalFormat("0");
|
Methods Summary |
---|
public java.lang.StringBuffer | format(java.lang.Object on, java.lang.StringBuffer sb, java.text.FieldPosition fp)
if (on instanceof String) {
String son = (String)on;
if (son.length() == 0) {
return sb.append("0B");
}
on = parseObject(son, null);
}
if (!(on instanceof Long)) {
throw new IllegalArgumentException("Argument " + on + " must be String or Long");
}
long n = ((Long)on).longValue();
sb.append(format(n));
return sb;
| public java.lang.String | format(double n)Format a double as a Scaled Numeral; just truncate to a
long, and call format(long).
return format((long)n);
| public java.lang.String | format(long number)Format a given long as a Scaled Numeral.
This method is the REAL FORMATTING ENGINE.
long fract = 0;
int unit = NONE;
StringBuffer buf = new StringBuffer();
long abval = Math.abs(number);
for (int i = 1/*!*/; i < scale_factors.length; i++) {
if (abval < scale_factors[i]) {
unit = units[i-1];
fract = i == 1 ? 0 : abval % scale_factors[i-1];
number /= scale_factors[i-1];
break;
}
}
if (fract < 0)
fract = -fract;
/* scale fraction to one digit (truncate, not round) */
while (fract>9)
fract /= 10;
if (number == 0)
return "0B";
else if (unit == NONE || number >= 100 || number <= -100) {
buf.append(df.format(number)).append(scale_chars[unit]);
} else {
buf.append(df.format(number)).append('.").
append(fract).append(scale_chars[unit]);
}
return buf.toString();
| public java.lang.Object | parseObject(java.lang.String s, java.text.ParsePosition where)Parse a String expected to contain a number in Human Scaled Form.
int i, sign = 0, fract_digits = 0;
long scale_fact = 1, whole = 0;
long fpart = 0;
if (s == null)
return null;
char[] b = s.trim().toCharArray();
int p = 0; // the index into b; the # of chars we've scanned.
/* Then at most one leading + or - */
while (b[p] == '-" || b[p] == '+") {
if (b[p] == '-") {
if (sign != 0)
throw new NumberFormatException(
"Number " + s + " has more than one sign.");
sign = -1;
++p;
} else if (b[p] == '+") {
if (sign != 0)
throw new NumberFormatException(
"Number " + s + " has more than one sign.");
sign = +1;
++p;
}
}
/* Main loop: Scan digits, find decimal point, if present.
* We don't allow exponentials, so no scientific notation
* (but note that E for Exa might look like e to some!).
* Advance 'p' to end, to get scale factor.
*/
for (; p<b.length && (Character.isDigit(b[p]) || b[p]=='."); ++p) {
int ndigits = 0;
if (b[p] == '.") {
if (fract_digits>0) {
throw new NumberFormatException(
"Number " + s + " has more than one decimal point ");
}
fract_digits = 1;
continue;
}
i = (b[p]) - '0"; // whew! finally a digit we can use
if (fract_digits > 0) { // fractional digit
if (fract_digits >= MAX_DIGITS)
throw new NumberFormatException("Number too large");
fpart *= 10;
fpart += i;
++fract_digits; // track for later scaling
} else { // normal digit
if (++ndigits >= MAX_DIGITS)
throw new NumberFormatException("Number too large");
whole *= 10;
whole += i;
}
}
/* printf("whole=%qd, fpart %ld, fract_digits %ld\n",
* whole, fpart, fract_digits);
*/
if (sign < 0) {
whole *= sign;
fpart *= sign;
}
/* If no scale factor given, we're done. fraction is discarded. */
if (p >= b.length) {
return new Long(whole);
}
/* Validate scale factor, and scale whole and fraction by it. */
for (i = 0; i < scale_factors.length; i++) {
if (b[p] == scale_chars[i] ||
b[p] == Character.toLowerCase(scale_chars[i])) {
// XXX if digits after this, throw exception
scale_fact = scale_factors[i];
// scale whole part: easy
whole *= scale_fact;
/* truncate fpart so it does't overflow.
* then scale fractional part.
*/
while (fpart >= LLONG_MAX / scale_fact) {
fpart /= 10;
fract_digits--;
}
fpart *= scale_fact;
if (fract_digits > 0) {
for (i = 0; i < fract_digits -1; i++)
fpart /= 10;
}
whole += fpart;
return new Long(whole);
}
}
throw new IllegalArgumentException("invalid scale factor " + b[p]);
| public java.lang.Object | parseObject(java.lang.String arg0)
return parseObject(arg0, null);
|
|