1 /* java.math.BigDecimal -- Arbitrary precision decimals.
2 Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
40 import java
.math
.BigInteger
;
42 public class BigDecimal
extends Number
implements Comparable
44 private BigInteger intVal
;
46 private static final long serialVersionUID
= 6108874887143696463L;
48 private final static BigDecimal ZERO
=
49 new BigDecimal (BigInteger
.valueOf (0), 0);
51 private final static BigDecimal ONE
=
52 new BigDecimal (BigInteger
.valueOf (1), 0);
54 public final static int ROUND_UP
= 0;
55 public final static int ROUND_DOWN
= 1;
56 public final static int ROUND_CEILING
= 2;
57 public final static int ROUND_FLOOR
= 3;
58 public final static int ROUND_HALF_UP
= 4;
59 public final static int ROUND_HALF_DOWN
= 5;
60 public final static int ROUND_HALF_EVEN
= 6;
61 public final static int ROUND_UNNECESSARY
= 7;
63 public BigDecimal (BigInteger num
)
68 public BigDecimal (BigInteger num
, int scale
) throws NumberFormatException
71 throw new NumberFormatException ("scale of " + scale
+ " is < 0");
76 public BigDecimal (double num
) throws NumberFormatException
78 if (Double
.isInfinite (num
) || Double
.isNaN (num
))
79 throw new NumberFormatException ("invalid argument: " + num
);
80 // Note we can't convert NUM to a String and then use the
81 // String-based constructor. The BigDecimal documentation makes
82 // it clear that the two constructors work differently.
84 final int mantissaBits
= 52;
85 final int exponentBits
= 11;
86 final long mantMask
= (1L << mantissaBits
) - 1;
87 final long expMask
= (1L << exponentBits
) - 1;
89 long bits
= Double
.doubleToLongBits (num
);
90 long mantissa
= bits
& mantMask
;
91 long exponent
= (bits
>>> mantissaBits
) & expMask
;
92 boolean denormal
= exponent
== 0;
93 // Correct the exponent for the bias.
94 exponent
-= denormal ?
1022 : 1023;
95 // Now correct the exponent to account for the bits to the right
97 exponent
-= mantissaBits
;
98 // Ordinary numbers have an implied leading `1' bit.
100 mantissa
|= (1L << mantissaBits
);
102 // Shave off factors of 10.
103 while (exponent
< 0 && (mantissa
& 1) == 0)
109 intVal
= BigInteger
.valueOf (bits
< 0 ?
- mantissa
: mantissa
);
112 // We have MANTISSA * 2 ^ (EXPONENT).
113 // Since (1/2)^N == 5^N * 10^-N we can easily convert this
114 // into a power of 10.
115 scale
= (int) (- exponent
);
116 BigInteger mult
= BigInteger
.valueOf (5).pow (scale
);
117 intVal
= intVal
.multiply (mult
);
121 intVal
= intVal
.shiftLeft ((int) exponent
);
126 public BigDecimal (String num
) throws NumberFormatException
128 int len
= num
.length();
129 int start
= 0, point
= 0;
131 boolean negative
= false;
132 if (num
.charAt(0) == '+')
137 else if (num
.charAt(0) == '-')
146 char c
= num
.charAt (point
);
150 throw new NumberFormatException ("multiple `.'s in number");
153 else if (c
== 'e' || c
== 'E')
155 else if (Character
.digit (c
, 10) < 0)
156 throw new NumberFormatException ("unrecognized character: " + c
);
163 val
= num
.substring (start
, dot
) + num
.substring (dot
+ 1, point
);
164 scale
= point
- 1 - dot
;
168 val
= num
.substring (start
, point
);
171 if (val
.length () == 0)
172 throw new NumberFormatException ("no digits seen");
176 intVal
= new BigInteger (val
);
178 // Now parse exponent.
182 if (num
.charAt(point
) == '+')
186 throw new NumberFormatException ("no exponent following e or E");
190 int exp
= Integer
.parseInt (num
.substring (point
));
196 intVal
= intVal
.multiply (BigInteger
.valueOf (10).pow (exp
));
202 catch (NumberFormatException ex
)
204 throw new NumberFormatException ("malformed exponent");
209 public static BigDecimal
valueOf (long val
)
211 return valueOf (val
, 0);
214 public static BigDecimal
valueOf (long val
, int scale
)
215 throws NumberFormatException
217 if ((scale
== 0) && ((int)val
== val
))
226 return new BigDecimal (BigInteger
.valueOf (val
), scale
);
229 public BigDecimal
add (BigDecimal val
)
231 // For addition, need to line up decimals. Note that the movePointRight
232 // method cannot be used for this as it might return a BigDecimal with
233 // scale == 0 instead of the scale we need.
234 BigInteger op1
= intVal
;
235 BigInteger op2
= val
.intVal
;
236 if (scale
< val
.scale
)
237 op1
= op1
.multiply (BigInteger
.valueOf (10).pow (val
.scale
- scale
));
238 else if (scale
> val
.scale
)
239 op2
= op2
.multiply (BigInteger
.valueOf (10).pow (scale
- val
.scale
));
241 return new BigDecimal (op1
.add (op2
), Math
.max (scale
, val
.scale
));
244 public BigDecimal
subtract (BigDecimal val
)
246 return this.add(val
.negate());
249 public BigDecimal
multiply (BigDecimal val
)
251 return new BigDecimal (intVal
.multiply (val
.intVal
), scale
+ val
.scale
);
254 public BigDecimal
divide (BigDecimal val
, int roundingMode
)
255 throws ArithmeticException
, IllegalArgumentException
257 return divide (val
, scale
, roundingMode
);
260 public BigDecimal
divide(BigDecimal val
, int newScale
, int roundingMode
)
261 throws ArithmeticException
, IllegalArgumentException
263 if (roundingMode
< 0 || roundingMode
> 7)
265 new IllegalArgumentException("illegal rounding mode: " + roundingMode
);
268 throw new ArithmeticException ("scale is negative: " + newScale
);
270 if (intVal
.signum () == 0) // handle special case of 0.0/0.0
271 return newScale
== 0 ? ZERO
: new BigDecimal (ZERO
.intVal
, newScale
);
273 // Ensure that pow gets a non-negative value.
274 int valScale
= val
.scale
;
275 BigInteger valIntVal
= val
.intVal
;
276 int power
= newScale
- (scale
- val
.scale
);
279 // Effectively increase the scale of val to avoid an
280 // ArithmeticException for a negative power.
281 valIntVal
= valIntVal
.multiply (BigInteger
.valueOf (10).pow (-power
));
285 BigInteger dividend
= intVal
.multiply (BigInteger
.valueOf (10).pow (power
));
287 BigInteger parts
[] = dividend
.divideAndRemainder (valIntVal
);
289 BigInteger unrounded
= parts
[0];
290 if (parts
[1].signum () == 0) // no remainder, no rounding necessary
291 return new BigDecimal (unrounded
, newScale
);
293 if (roundingMode
== ROUND_UNNECESSARY
)
294 throw new ArithmeticException ("newScale is not large enough");
296 int sign
= intVal
.signum () * valIntVal
.signum ();
298 if (roundingMode
== ROUND_CEILING
)
299 roundingMode
= (sign
> 0) ? ROUND_UP
: ROUND_DOWN
;
300 else if (roundingMode
== ROUND_FLOOR
)
301 roundingMode
= (sign
< 0) ? ROUND_UP
: ROUND_DOWN
;
304 // half is -1 if remainder*2 < positive intValue (*power), 0 if equal,
305 // 1 if >. This implies that the remainder to round is less than,
306 // equal to, or greater than half way to the next digit.
307 BigInteger posRemainder
308 = parts
[1].signum () < 0 ? parts
[1].negate() : parts
[1];
309 valIntVal
= valIntVal
.signum () < 0 ? valIntVal
.negate () : valIntVal
;
310 int half
= posRemainder
.shiftLeft(1).compareTo(valIntVal
);
315 roundingMode
= (half
< 0) ? ROUND_DOWN
: ROUND_UP
;
317 case ROUND_HALF_DOWN
:
318 roundingMode
= (half
> 0) ? ROUND_UP
: ROUND_DOWN
;
320 case ROUND_HALF_EVEN
:
322 roundingMode
= ROUND_DOWN
;
324 roundingMode
= ROUND_UP
;
325 else if (unrounded
.testBit(0)) // odd, then ROUND_HALF_UP
326 roundingMode
= ROUND_UP
;
327 else // even, ROUND_HALF_DOWN
328 roundingMode
= ROUND_DOWN
;
333 if (roundingMode
== ROUND_UP
)
334 unrounded
= unrounded
.add (BigInteger
.valueOf (sign
> 0 ?
1 : -1));
336 // roundingMode == ROUND_DOWN
337 return new BigDecimal (unrounded
, newScale
);
340 public int compareTo (BigDecimal val
)
342 if (scale
== val
.scale
)
343 return intVal
.compareTo (val
.intVal
);
345 BigInteger thisParts
[] =
346 intVal
.divideAndRemainder (BigInteger
.valueOf (10).pow (scale
));
347 BigInteger valParts
[] =
348 val
.intVal
.divideAndRemainder (BigInteger
.valueOf (10).pow (val
.scale
));
351 if ((compare
= thisParts
[0].compareTo (valParts
[0])) != 0)
354 // quotients are the same, so compare remainders
356 // remove trailing zeros
357 if (thisParts
[1].equals (BigInteger
.valueOf (0)) == false)
358 while (thisParts
[1].mod (BigInteger
.valueOf (10)).equals
359 (BigInteger
.valueOf (0)))
360 thisParts
[1] = thisParts
[1].divide (BigInteger
.valueOf (10));
362 if (valParts
[1].equals(BigInteger
.valueOf (0)) == false)
363 while (valParts
[1].mod (BigInteger
.valueOf (10)).equals
364 (BigInteger
.valueOf (0)))
365 valParts
[1] = valParts
[1].divide (BigInteger
.valueOf (10));
368 return thisParts
[1].compareTo (valParts
[1]);
371 public int compareTo (Object val
)
373 return(compareTo((BigDecimal
)val
));
376 public boolean equals (Object o
)
378 return (o
instanceof BigDecimal
379 && scale
== ((BigDecimal
) o
).scale
380 && compareTo ((BigDecimal
) o
) == 0);
383 public int hashCode()
385 return intValue() ^ scale
;
388 public BigDecimal
max (BigDecimal val
)
390 switch (compareTo (val
))
399 public BigDecimal
min (BigDecimal val
)
401 switch (compareTo (val
))
410 public BigDecimal
movePointLeft (int n
)
412 return (n
< 0) ?
movePointRight (-n
) : new BigDecimal (intVal
, scale
+ n
);
415 public BigDecimal
movePointRight (int n
)
418 return movePointLeft (-n
);
421 return new BigDecimal (intVal
, scale
- n
);
423 return new BigDecimal (intVal
.multiply
424 (BigInteger
.valueOf (10).pow (n
- scale
)), 0);
429 return intVal
.signum ();
437 public BigInteger
unscaledValue()
442 public BigDecimal
abs ()
444 return new BigDecimal (intVal
.abs (), scale
);
447 public BigDecimal
negate ()
449 return new BigDecimal (intVal
.negate (), scale
);
452 public String
toString ()
454 String bigStr
= intVal
.toString();
458 boolean negative
= (bigStr
.charAt(0) == '-');
460 int point
= bigStr
.length() - scale
- (negative ?
1 : 0);
462 StringBuffer sb
= new StringBuffer(bigStr
.length() + 2 +
463 (point
<= 0 ?
(-point
+ 1) : 0));
468 sb
.append('0').append('.');
474 sb
.append(bigStr
.substring(negative ?
1 : 0));
479 sb
.insert(point
+ (negative ?
1 : 0), '.');
481 return sb
.toString();
484 public BigInteger
toBigInteger ()
486 return scale
== 0 ? intVal
:
487 intVal
.divide (BigInteger
.valueOf (10).pow (scale
));
490 public int intValue ()
492 return toBigInteger ().intValue ();
495 public long longValue ()
497 return toBigInteger().longValue();
500 public float floatValue()
502 return Float
.valueOf(toString()).floatValue();
505 public double doubleValue()
507 return Double
.valueOf(toString()).doubleValue();
510 public BigDecimal
setScale (int scale
) throws ArithmeticException
512 return setScale (scale
, ROUND_UNNECESSARY
);
515 public BigDecimal
setScale (int scale
, int roundingMode
)
516 throws ArithmeticException
, IllegalArgumentException
518 return divide (ONE
, scale
, roundingMode
);