This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: FYI: BigDecimal constructors


I'm checking this in.  This fixes some problems with the BigDecimal
constructors, and brings them into 1.3 compatibility.  I have a mini
Mauve test for this which I'll check in soon.  I'm also checking this
in to Classpath.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* java/math/BigDecimal.java (BigDecimal(double)): Rewrote.
	(BigDecimal(String)): Likewise.

Index: java/math/BigDecimal.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/math/BigDecimal.java,v
retrieving revision 1.4
diff -u -r1.4 BigDecimal.java
--- java/math/BigDecimal.java 2001/01/10 10:26:34 1.4
+++ java/math/BigDecimal.java 2001/11/25 19:26:09
@@ -28,7 +28,8 @@
 
 import java.math.BigInteger;
 
-public class BigDecimal extends Number implements Comparable {
+public class BigDecimal extends Number implements Comparable
+{
   private BigInteger intVal;
   private int scale;
   private static final long serialVersionUID = 6108874887143696463L;
@@ -63,16 +64,119 @@
 
   public BigDecimal (double num) throws NumberFormatException 
   {
-    this (Double.toString (num));
+    if (Double.isInfinite (num) || Double.isNaN (num))
+      throw new NumberFormatException ("invalid argument: " + num);
+    // Note we can't convert NUM to a String and then use the
+    // String-based constructor.  The BigDecimal documentation makes
+    // it clear that the two constructors work differently.
+
+    final int mantissaBits = 52;
+    final int exponentBits = 11;
+    final long mantMask = (1L << mantissaBits) - 1;
+    final long expMask = (1L << exponentBits) - 1;
+
+    long bits = Double.doubleToLongBits (num);
+    long mantissa = bits & mantMask;
+    long exponent = (bits >>> mantissaBits) & expMask;
+    boolean denormal = exponent == 0;
+    // Correct the exponent for the bias.
+    exponent -= denormal ? 1022 : 1023;
+    // Now correct the exponent to account for the bits to the right
+    // of the decimal.
+    exponent -= mantissaBits;
+    // Ordinary numbers have an implied leading `1' bit.
+    if (! denormal)
+      mantissa |= (1L << mantissaBits);
+
+    // Shave off factors of 10.
+    while (exponent < 0 && (mantissa & 1) == 0)
+      {
+	++exponent;
+	mantissa >>= 1;
+      }
+
+    intVal = BigInteger.valueOf (bits < 0 ? - mantissa : mantissa);
+    if (exponent < 0)
+      {
+	// We have MANTISSA * 2 ^ (EXPONENT).
+	// Since (1/2)^N == 5^N * 10^-N we can easily convert this
+	// into a power of 10.
+	scale = (int) (- exponent);
+	BigInteger mult = BigInteger.valueOf (5).pow (scale);
+	intVal = intVal.multiply (mult);
+      }
+    else
+      {
+	intVal = intVal.shiftLeft ((int) exponent);
+	scale = 0;
+      }
   }
 
   public BigDecimal (String num) throws NumberFormatException 
   {
-    int point = num.indexOf('.');
-    this.intVal = new BigInteger (point == -1 ? num :
-			       num.substring (0, point) + 
-			       num.substring (point + 1));
-    scale = num.length() - (point == -1 ? num.length () : point + 1);
+    int len = num.length();
+    int start = 0, point = 0;
+    int dot = -1;
+    boolean negative = false;
+    if (num.charAt(0) == '+')
+      {
+	++start;
+	++point;
+      }
+    else if (num.charAt(0) == '-')
+      {
+	++start;
+	++point;
+	negative = true;
+      }
+
+    while (point < len)
+      {
+	char c = num.charAt (point);
+	if (c == '.')
+	  {
+	    if (dot >= 0)
+	      throw new NumberFormatException ("multiple `.'s in number");
+	    dot = point;
+	  }
+	else if (c == 'e' || c == 'E')
+	  break;
+	else if (Character.digit (c, 10) < 0)
+	  throw new NumberFormatException ("unrecognized character: " + c);
+	++point;
+      }
+
+    String val;
+    if (dot >= 0)
+      {
+	val = num.substring (start, dot) + num.substring (dot + 1, point);
+	scale = point - 1 - dot;
+      }
+    else
+      {
+	val = num.substring (start, point);
+	scale = 0;
+      }
+    if (val.length () == 0)
+      throw new NumberFormatException ("no digits seen");
+
+    if (negative)
+      val = "-" + val;
+    intVal = new BigInteger (val);
+
+    // Now parse exponent.
+    if (point < len)
+      {
+	int exp = Integer.parseInt (num.substring (point + 1));
+	exp -= scale;
+	if (exp > 0)
+	  {
+	    intVal = intVal.multiply (BigInteger.valueOf (10).pow (exp));
+	    scale = 0;
+	  }
+	else
+	  scale = - exp;
+      }
   }
 
   public static BigDecimal valueOf (long val) 
@@ -338,7 +442,6 @@
       intVal.divide (BigInteger.valueOf (10).pow (scale));
   }
 
-
   public int intValue () 
   {
     return toBigInteger ().intValue ();


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]