1. /*
  2. * @(#)MathContext.java 1.2 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /*
  8. * @(#)MathContext.java 1.x 01/xx/xx
  9. *
  10. * Copyright IBM Corporation, 1997, 2001. All Rights Reserved.
  11. *
  12. * This software is the proprietary information of Sun Microsystems, Inc.
  13. * and IBM Corporation. Use is subject to license terms.
  14. *
  15. */
  16. package java.math;
  17. import java.io.*;
  18. /**
  19. * Immutable objects which encapsulate the context settings which
  20. * describe certain rules for numerical operators, such as those
  21. * implemented by the {@link BigDecimal} class.
  22. *
  23. * <p>The base-independent settings are:
  24. * <ol>
  25. * <li><tt>precision</tt>:
  26. * the number of digits to be used for an operation; results are
  27. * rounded to this precision
  28. *
  29. * <li><tt>roundingMode</tt>:
  30. * a {@link RoundingMode} object which specifies the algorithm to be
  31. * used for rounding.
  32. * </ol>
  33. *
  34. * @see BigDecimal
  35. * @see RoundingMode
  36. * @author Mike Cowlishaw
  37. * @author Joseph D. Darcy
  38. */
  39. public final class MathContext implements Serializable {
  40. /* ----- Constants ----- */
  41. // defaults for constructors
  42. private static final int DEFAULT_DIGITS = 9;
  43. private static final RoundingMode DEFAULT_ROUNDINGMODE = RoundingMode.HALF_UP;
  44. // Smallest values for digits (Maximum is Integer.MAX_VALUE)
  45. private static final int MIN_DIGITS = 0;
  46. // Serialization version
  47. private static final long serialVersionUID = 5579720004786848255L;
  48. /* ----- Public Properties ----- */
  49. /**
  50. * A <tt>MathContext</tt> object whose settings have the values
  51. * required for unlimited precision arithmetic.
  52. * The values of the settings are:
  53. * <code>
  54. * precision=0 roundingMode=HALF_UP
  55. * </code>
  56. */
  57. public static final MathContext UNLIMITED =
  58. new MathContext(0, RoundingMode.HALF_UP);
  59. /**
  60. * A <tt>MathContext</tt> object with a precision setting
  61. * matching the IEEE 754R Decimal32 format, 7 digits, and a
  62. * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
  63. * IEEE 754R default.
  64. */
  65. public static final MathContext DECIMAL32 =
  66. new MathContext(7, RoundingMode.HALF_EVEN);
  67. /**
  68. * A <tt>MathContext</tt> object with a precision setting
  69. * matching the IEEE 754R Decimal64 format, 16 digits, and a
  70. * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
  71. * IEEE 754R default.
  72. */
  73. public static final MathContext DECIMAL64 =
  74. new MathContext(16, RoundingMode.HALF_EVEN);
  75. /**
  76. * A <tt>MathContext</tt> object with a precision setting
  77. * matching the IEEE 754R Decimal128 format, 34 digits, and a
  78. * rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
  79. * IEEE 754R default.
  80. */
  81. public static final MathContext DECIMAL128 =
  82. new MathContext(34, RoundingMode.HALF_EVEN);
  83. /* ----- Shared Properties ----- */
  84. /**
  85. * The number of digits to be used for an operation. A value of 0
  86. * indicates that unlimited precision (as many digits as are
  87. * required) will be used. Note that leading zeros (in the
  88. * coefficient of a number) are never significant.
  89. *
  90. * <p><tt>precision</tt> will always be non-negative.
  91. *
  92. * @serial
  93. */
  94. final int precision;
  95. /**
  96. * The rounding algorithm to be used for an operation.
  97. *
  98. * @see RoundingMode
  99. * @serial
  100. */
  101. final RoundingMode roundingMode;
  102. /**
  103. * Lookaside for the rounding points (the numbers which determine
  104. * whether the coefficient of a number will require rounding).
  105. * These will be present if precision>0 and
  106. * precision<=MAX_LOOKASIDE. In this case they will share the
  107. * <tt>BigInteger int[]</tt> array. Note that the transients
  108. * cannot be <tt>final</tt> because they are reconstructed on
  109. * deserialization.
  110. */
  111. transient BigInteger roundingMax = null;
  112. transient BigInteger roundingMin = null;
  113. private static final int MAX_LOOKASIDE = 1000;
  114. /* ----- Constructors ----- */
  115. /**
  116. * Constructs a new <tt>MathContext</tt> with the specified
  117. * precision and the {@link RoundingMode#HALF_UP HALF_UP} rounding
  118. * mode.
  119. *
  120. * @param setPrecision The non-negative <tt>int</tt> precision setting.
  121. * @throws IllegalArgumentException <tt>setPrecision</tt> parameter less
  122. * than zero.
  123. */
  124. public MathContext(int setPrecision) {
  125. this(setPrecision, DEFAULT_ROUNDINGMODE);
  126. return;
  127. }
  128. /**
  129. * Constructs a new <tt>MathContext</tt> with a specified
  130. * precision and rounding mode.
  131. *
  132. * @param setPrecision The non-negative <tt>int</tt> precision setting.
  133. * @param setRoundingMode The rounding mode to use.
  134. * @throws IllegalArgumentException <tt>setPrecision</tt> parameter less
  135. * than zero.
  136. */
  137. public MathContext(int setPrecision,
  138. RoundingMode setRoundingMode) {
  139. if (setPrecision < MIN_DIGITS)
  140. throw new IllegalArgumentException("Digits < 0");
  141. if (setRoundingMode == null)
  142. throw new NullPointerException("null RoundingMode");
  143. precision = setPrecision;
  144. if (precision > 0 && precision <= MAX_LOOKASIDE) {
  145. roundingMax = BigInteger.TEN.pow(precision);
  146. roundingMin = roundingMax.negate();
  147. }
  148. roundingMode = setRoundingMode;
  149. return;
  150. }
  151. /**
  152. * Constructs a new <tt>MathContext</tt> from a string.
  153. *
  154. * The string must be in the same format as that produced by the
  155. * {@link #toString} method.
  156. *
  157. * <p>An <tt>IllegalArgumentException</tt> is thrown if the precision
  158. * section of the string is out of range (< 0) or the string is
  159. * not in the format created by the {@link #toString} method.
  160. *
  161. * @param val The string to be parsed
  162. * @throws IllegalArgumentException precision parameter out of range
  163. * or incorrect format
  164. */
  165. public MathContext(String val) {
  166. boolean bad = false;
  167. int setPrecision;
  168. if (val == null)
  169. throw new NullPointerException("null String");
  170. try { // any error here is a string format problem
  171. if (!val.startsWith("precision=")) throw new RuntimeException();
  172. int fence = val.indexOf(' '); // could be -1
  173. int off = 10; // where value starts
  174. setPrecision = Integer.parseInt(val.substring(10, fence));
  175. if (!val.startsWith("roundingMode=", fence+1))
  176. throw new RuntimeException();
  177. off = fence + 1 + 13;
  178. String str = val.substring(off, val.length());
  179. roundingMode = RoundingMode.valueOf(str);
  180. } catch (RuntimeException re) {
  181. throw new IllegalArgumentException("bad string format");
  182. }
  183. if (setPrecision < MIN_DIGITS)
  184. throw new IllegalArgumentException("Digits < 0");
  185. // the other parameters cannot be invalid if we got here
  186. precision = setPrecision;
  187. if (precision > 0 && precision <= MAX_LOOKASIDE) {
  188. roundingMax = BigInteger.TEN.pow(precision);
  189. roundingMin = roundingMax.negate();
  190. }
  191. }
  192. /**
  193. * Returns the <tt>precision</tt> setting.
  194. * This value is always non-negative.
  195. *
  196. * @return an <tt>int</tt> which is the value of the <tt>precision</tt>
  197. * setting
  198. */
  199. public int getPrecision() {
  200. return precision;
  201. }
  202. /**
  203. * Returns the roundingMode setting.
  204. * This will be one of
  205. * {@link RoundingMode#CEILING},
  206. * {@link RoundingMode#DOWN},
  207. * {@link RoundingMode#FLOOR},
  208. * {@link RoundingMode#HALF_DOWN},
  209. * {@link RoundingMode#HALF_EVEN},
  210. * {@link RoundingMode#HALF_UP},
  211. * {@link RoundingMode#UNNECESSARY}, or
  212. * {@link RoundingMode#UP}.
  213. *
  214. * @return a <tt>RoundingMode</tt> object which is the value of the
  215. * <tt>roundingMode</tt> setting
  216. */
  217. public RoundingMode getRoundingMode() {
  218. return roundingMode;
  219. }
  220. /**
  221. * Compares this <tt>MathContext</tt> with the specified
  222. * <tt>Object</tt> for equality.
  223. *
  224. * @param x <tt>Object</tt> to which this <tt>MathContext</tt> is to
  225. * be compared.
  226. * @return <tt>true</tt> if and only if the specified <tt>Object</tt> is
  227. * a <tt>MathContext</tt> object which has exactly the same
  228. * settings as this object.
  229. */
  230. public boolean equals(Object x){
  231. MathContext mc;
  232. if (!(x instanceof MathContext))
  233. return false;
  234. mc = (MathContext) x;
  235. return mc.precision == this.precision
  236. && mc.roundingMode == this.roundingMode; // no need for .equals()
  237. }
  238. /**
  239. * Returns the hash code for this <tt>MathContext</tt>.
  240. *
  241. * @return hash code for this <tt>MathContext</tt>
  242. */
  243. public int hashCode() {
  244. return this.precision + roundingMode.hashCode() * 59;
  245. }
  246. /**
  247. * Returns the string representation of this <tt>MathContext</tt>.
  248. * The <tt>String</tt> returned represents the settings of the
  249. * <tt>MathContext</tt> object as two space-delimited words
  250. * (separated by a single space character, <tt>'\u0020'</tt>,
  251. * and with no leading or trailing white space), as follows:
  252. * <ol>
  253. * <li>
  254. * The string <tt>"precision="</tt>, immediately followed
  255. * by the value of the precision setting as a numeric string as if
  256. * generated by the {@link Integer#toString(int) Integer.toString}
  257. * method.
  258. *
  259. * <li>
  260. * The string <tt>"roundingMode="</tt>, immediately
  261. * followed by the value of the <tt>roundingMode</tt> setting as a
  262. * word. This word will be the same as the name of the
  263. * corresponding public constant in the {@link RoundingMode}
  264. * enum.
  265. * </ol>
  266. * <p>
  267. * For example:
  268. * <pre>
  269. * precision=9 roundingMode=HALF_UP
  270. * </pre>
  271. *
  272. * Additional words may be appended to the result of
  273. * <tt>toString</tt> in the future if more properties are added to
  274. * this class.
  275. *
  276. * @return a <tt>String</tt> representing the context settings.
  277. */
  278. public java.lang.String toString() {
  279. return "precision=" + precision + " " +
  280. "roundingMode=" + roundingMode.toString();
  281. }
  282. // Private methods
  283. /**
  284. * Reconstitute the <tt>MathContext</tt> instance from a stream (that is,
  285. * deserialize it).
  286. *
  287. * @param s the stream being read.
  288. */
  289. private synchronized void readObject(java.io.ObjectInputStream s)
  290. throws java.io.IOException, ClassNotFoundException {
  291. s.defaultReadObject(); // read in all fields
  292. // validate possibly bad fields
  293. if (precision < MIN_DIGITS) {
  294. String message = "MathContext: invalid digits in stream";
  295. throw new java.io.StreamCorruptedException(message);
  296. }
  297. if (roundingMode == null) {
  298. String message = "MathContext: null roundingMode in stream";
  299. throw new java.io.StreamCorruptedException(message);
  300. }
  301. // Set the lookaside, if applicable
  302. if (precision <= MAX_LOOKASIDE) {
  303. roundingMax = BigInteger.TEN.pow(precision);
  304. roundingMin = roundingMax.negate();
  305. }
  306. }
  307. }