Here you can find the source of bigDecimalFromString(String s)
public static java.math.BigDecimal bigDecimalFromString(String s)
//package com.java2s; // Use is governed by the terms of the J/Link license agreement, which can be found at import java.math.MathContext; public class Main { public static java.math.BigDecimal bigDecimalFromString(String s) { // Need to accommodate InputForm bigdecimal, e.g. -1.234567...89e35\0`53.101 or -1.234567...89`53.101*^35\0`53.101. // Note that I probably need to respect the precision info that is supplied via the numbermark. // The idea is to extract the digits as a big integer and then determine the scale. These // are the components we need for the BigDecimal constructor. int len = s.length(); byte[] data = s.getBytes(); // For some reason the kernel can write real numbers with spaces embedded and only junk afterwards, // and when reading reals MLGetString and related funcs will convert spaces into 0 chars (\0, not '0'), // so the first step is to truncate the string at the first \0 char (actually, because it is not // clear that all versions of the kernel will do this conversion, truncate at either ' ' or \0). int i;//from ww w . j ava 2 s. c om int tickPos = -1; boolean finishedWithDigits = false; for (i = 0; i < len; i++) { byte b = data[i]; if ((b == 0 || b == 32) && !finishedWithDigits) { len = i; finishedWithDigits = true; } else if (b == 96) { tickPos = i; } } // Get precision info, if present. int precision = -1; /* This was an attempt to get precision info from M reals into the BigDecimal objects using new features in * Java 5. I think it is working, although other changes are needed to use it correctly (MathLinkImplBase.put(Object), * where BigDecimals are written onto a link). There are issues with this idea, and M reals can never be converted * into BigDecimal with complete accuracy (for example, M reals can have non-integer precision). I am not * convinced right now that this is the right thing to do, or at least that there wouldn't be unintended consequences * or code breakage, so I am leaving it commented out. if (tickPos > 0) { int startOfPrecision = tickPos + 1; int endOfPrecision = startOfPrecision; while (endOfPrecision < len && Character.isDigit(data[endOfPrecision])) endOfPrecision++; // At end of above loop, endOfPrecision points to the first position past the end of precision info. It could // be a decimal point, since precision info from M is often non-integer, but we can only handle integer // precision. The end could also be because we hit the end of the string, or we hit the *^ chars. if (endOfPrecision > startOfPrecision) precision = Integer.parseInt(s.substring(startOfPrecision, endOfPrecision)); } */ byte[] digitBuf = new byte[len]; int digitCount = 0; int decimalPos = -1; boolean isNegative = false; // First get the digits from the number, ignoring the exponent. Record position of the decimal point. for (i = 0; i < len; i++) { byte b = data[i]; if (b >= 48 && b <= 57) { // Digit digitBuf[digitCount++] = b; } else if (b == 45) { // Minus sign isNegative = true; digitBuf[digitCount++] = b; } else if (b == 46) { decimalPos = i; } else { // End of digits for unscaled value part of BigDecimal. break; } } // Note that the value of i at the end if this loop is used later. // Now create in unscaledValue an integer that contains all the digits of the original real, but no decimal point. String unscaledValue = new String(digitBuf, 0, digitCount); // this scale value will be modified later if there is an exponent. int scale = decimalPos != -1 ? digitCount - decimalPos : 0; // Advance i to point to first char past either 'e' or '*^'. That position is the start of the exponent. for (; i < len; i++) { byte b = data[i]; if (b == 101) { // e (old style number format) i++; break; } else if (b == 42) { // * (new style number format) i += 2; break; } } // Now get exponent as an integer. Reuse digitBuf. digitCount = 0; for (; i < len; i++) { byte b = data[i]; if (b == 45 || (b >= 48 && b <= 57)) { // Minus sign or digit. digitBuf[digitCount++] = b; } else if (b == 43) { // Plus sign. Do nothing (Integer.parseInt() cannot handle a leading + sign, if you can believe that). } else { break; } } if (digitCount > 0) { int exponent = Integer.parseInt(new String(digitBuf, 0, digitCount)); scale -= exponent; } if (precision >= 0) return new java.math.BigDecimal(new java.math.BigInteger(unscaledValue), scale, new MathContext(precision)); else return new java.math.BigDecimal(new java.math.BigInteger(unscaledValue), scale); } }