in commons-math-legacy-core/src/main/java/org/apache/commons/math4/legacy/core/dfp/Dfp.java [333:529]
protected Dfp(final DfpField field, final String s) {
// initialize as if 0
mant = new int[field.getRadixDigits()];
sign = 1;
exp = 0;
nans = FINITE;
this.field = field;
boolean decimalFound = false;
final int rsize = 4; // size of radix in decimal digits
final int offset = 4; // Starting offset into Striped
final char[] striped = new char[getRadixDigits() * rsize + offset * 2];
// Check some special cases
if (s.equals(POS_INFINITY_STRING)) {
sign = (byte) 1;
nans = INFINITE;
return;
}
if (s.equals(NEG_INFINITY_STRING)) {
sign = (byte) -1;
nans = INFINITE;
return;
}
if (s.equals(NAN_STRING)) {
sign = (byte) 1;
nans = QNAN;
return;
}
// Check for scientific notation
int p = s.indexOf("e");
if (p == -1) { // try upper case?
p = s.indexOf("E");
}
final String fpdecimal;
int sciexp = 0;
if (p != -1) {
// scientific notation
fpdecimal = s.substring(0, p);
String fpexp = s.substring(p + 1);
boolean negative = false;
for (int i = 0; i < fpexp.length(); i++) {
if (fpexp.charAt(i) == '-') {
negative = true;
continue;
}
if (fpexp.charAt(i) >= '0' && fpexp.charAt(i) <= '9') {
sciexp = sciexp * 10 + fpexp.charAt(i) - '0';
}
}
if (negative) {
sciexp = -sciexp;
}
} else {
// normal case
fpdecimal = s;
}
// If there is a minus sign in the number then it is negative
if (fpdecimal.indexOf("-") != -1) {
sign = -1;
}
// First off, find all of the leading zeros, trailing zeros, and significant digits
p = 0;
// Move p to first significant digit
int decimalPos = 0;
for (;;) {
if (fpdecimal.charAt(p) >= '1' && fpdecimal.charAt(p) <= '9') {
break;
}
if (decimalFound && fpdecimal.charAt(p) == '0') {
decimalPos--;
}
if (fpdecimal.charAt(p) == '.') {
decimalFound = true;
}
p++;
if (p == fpdecimal.length()) {
break;
}
}
// Copy the string onto Stripped
int q = offset;
striped[0] = '0';
striped[1] = '0';
striped[2] = '0';
striped[3] = '0';
int significantDigits = 0;
for (;;) {
if (p == (fpdecimal.length())) {
break;
}
// Don't want to run pass the end of the array
if (q == mant.length * rsize + offset + 1) {
break;
}
if (fpdecimal.charAt(p) == '.') {
decimalFound = true;
decimalPos = significantDigits;
p++;
continue;
}
if (fpdecimal.charAt(p) < '0' || fpdecimal.charAt(p) > '9') {
p++;
continue;
}
striped[q] = fpdecimal.charAt(p);
q++;
p++;
significantDigits++;
}
// If the decimal point has been found then get rid of trailing zeros.
if (decimalFound && q != offset) {
for (;;) {
q--;
if (q == offset) {
break;
}
if (striped[q] == '0') {
significantDigits--;
} else {
break;
}
}
}
// special case of numbers like "0.00000"
if (decimalFound && significantDigits == 0) {
decimalPos = 0;
}
// Implicit decimal point at end of number if not present
if (!decimalFound) {
decimalPos = q - offset;
}
// Find the number of significant trailing zeros
q = offset; // set q to point to first sig digit
p = significantDigits - 1 + offset;
while (p > q) {
if (striped[p] != '0') {
break;
}
p--;
}
// Make sure the decimal is on a mod 10000 boundary
int i = ((rsize * 100) - decimalPos - sciexp % rsize) % rsize;
q -= i;
decimalPos += i;
// Make the mantissa length right by adding zeros at the end if necessary
while ((p - q) < (mant.length * rsize)) {
for (i = 0; i < rsize; i++) {
striped[++p] = '0';
}
}
// Ok, now we know how many trailing zeros there are,
// and where the least significant digit is
for (i = mant.length - 1; i >= 0; i--) {
mant[i] = (striped[q] - '0') * 1000 +
(striped[q + 1] - '0') * 100 +
(striped[q + 2] - '0') * 10 +
(striped[q + 3] - '0');
q += 4;
}
exp = (decimalPos + sciexp) / rsize;
if (q < striped.length) {
// Is there possible another digit?
round((striped[q] - '0') * 1000);
}
}