in src/main/java/org/apache/xmlgraphics/util/DoubleFormatUtil.java [80:180]
public static void formatDoublePrecise(double source, int decimals, int precision, StringBuffer target) {
if (isRoundedToZero(source, decimals, precision)) {
// Will always be rounded to 0
target.append('0');
return;
} else if (Double.isNaN(source) || Double.isInfinite(source)) {
// Cannot be formated
target.append(Double.toString(source));
return;
}
boolean negative = source < 0.0;
if (negative) {
source = -source;
// Done once and for all
target.append('-');
}
int scale = (source >= 1.0) ? decimals : precision;
// The only way to format precisely the double is to use the String
// representation of the double, and then to do mathematical integer operation on it.
String s = Double.toString(source);
if (source >= 1e-3 && source < 1e7) {
// Plain representation of double: "intPart.decimalPart"
int dot = s.indexOf('.');
String decS = s.substring(dot + 1);
int decLength = decS.length();
if (scale >= decLength) {
if ("0".equals(decS)) {
// source is a mathematical integer
target.append(s.substring(0, dot));
} else {
target.append(s);
// Remove trailing zeroes
for (int l = target.length() - 1; l >= 0 && target.charAt(l) == '0'; l--) {
target.setLength(l);
}
}
return;
} else if (scale + 1 < decLength) {
// ignore unnecessary digits
decLength = scale + 1;
decS = decS.substring(0, decLength);
}
long intP = Long.parseLong(s.substring(0, dot));
long decP = Long.parseLong(decS);
format(target, scale, intP, decP);
} else {
// Scientific representation of double: "x.xxxxxEyyy"
int dot = s.indexOf('.');
assert dot >= 0;
int exp = s.indexOf('E');
assert exp >= 0;
int exposant = Integer.parseInt(s.substring(exp + 1));
String intS = s.substring(0, dot);
String decS = s.substring(dot + 1, exp);
int decLength = decS.length();
if (exposant >= 0) {
int digits = decLength - exposant;
if (digits <= 0) {
// no decimal part,
// no rounding involved
target.append(intS);
target.append(decS);
for (int i = -digits; i > 0; i--) {
target.append('0');
}
} else if (digits <= scale) {
// decimal part precision is lower than scale,
// no rounding involved
target.append(intS);
target.append(decS.substring(0, exposant));
target.append('.');
target.append(decS.substring(exposant));
} else {
// decimalDigits > scale,
// Rounding involved
long intP = Long.parseLong(intS) * tenPow(exposant) + Long.parseLong(decS.substring(0, exposant));
long decP = Long.parseLong(decS.substring(exposant, exposant + scale + 1));
format(target, scale, intP, decP);
}
} else {
// Only a decimal part is supplied
exposant = -exposant;
int digits = scale - exposant + 1;
if (digits < 0) {
target.append('0');
} else if (digits == 0) {
long decP = Long.parseLong(intS);
format(target, scale, 0L, decP);
} else if (decLength < digits) {
long decP = Long.parseLong(intS) * tenPow(decLength + 1) + Long.parseLong(decS) * 10;
format(target, exposant + decLength, 0L, decP);
} else {
long subDecP = Long.parseLong(decS.substring(0, digits));
long decP = Long.parseLong(intS) * tenPow(digits) + subDecP;
format(target, scale, 0L, decP);
}
}
}
}