Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
MathUtils |
|
| 3.090909090909091;3.091 |
1 | /* |
|
2 | * Copyright 2003-2004 The Apache Software Foundation. |
|
3 | * |
|
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
|
5 | * you may not use this file except in compliance with the License. |
|
6 | * You may obtain a copy of the License at |
|
7 | * |
|
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
9 | * |
|
10 | * Unless required by applicable law or agreed to in writing, software |
|
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
13 | * See the License for the specific language governing permissions and |
|
14 | * limitations under the License. |
|
15 | */ |
|
16 | ||
17 | package org.apache.commons.math.util; |
|
18 | ||
19 | import java.math.BigDecimal; |
|
20 | ||
21 | /** |
|
22 | * Some useful additions to the built-in functions in {@link Math}. |
|
23 | * @version $Revision$ $Date: 2005-08-22 19:27:17 -0700 (Mon, 22 Aug 2005) $ |
|
24 | */ |
|
25 | public final class MathUtils { |
|
26 | ||
27 | /** -1.0 cast as a byte. */ |
|
28 | private static final byte NB = (byte)-1; |
|
29 | ||
30 | /** -1.0 cast as a short. */ |
|
31 | private static final short NS = (short)-1; |
|
32 | ||
33 | /** 1.0 cast as a byte. */ |
|
34 | private static final byte PB = (byte)1; |
|
35 | ||
36 | /** 1.0 cast as a short. */ |
|
37 | private static final short PS = (short)1; |
|
38 | ||
39 | /** 0.0 cast as a byte. */ |
|
40 | private static final byte ZB = (byte)0; |
|
41 | ||
42 | /** 0.0 cast as a short. */ |
|
43 | private static final short ZS = (short)0; |
|
44 | ||
45 | /** |
|
46 | * Private Constructor |
|
47 | */ |
|
48 | private MathUtils() { |
|
49 | 0 | super(); |
50 | 0 | } |
51 | ||
52 | /** |
|
53 | * Add two integers, checking for overflow. |
|
54 | * |
|
55 | * @param x an addend |
|
56 | * @param y an addend |
|
57 | * @return the sum <code>x+y</code> |
|
58 | * @throws ArithmeticException if the result can not be represented as an |
|
59 | * int |
|
60 | * @since 1.1 |
|
61 | */ |
|
62 | public static int addAndCheck(int x, int y) { |
|
63 | 22 | long s = (long)x + (long)y; |
64 | 22 | if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) { |
65 | 10 | throw new ArithmeticException("overflow: add"); |
66 | } |
|
67 | 12 | return (int)s; |
68 | } |
|
69 | ||
70 | /** |
|
71 | * Returns an exact representation of the <a |
|
72 | * href="http://mathworld.wolfram.com/BinomialCoefficient.html"> Binomial |
|
73 | * Coefficient</a>, "<code>n choose k</code>", the number of |
|
74 | * <code>k</code>-element subsets that can be selected from an |
|
75 | * <code>n</code>-element set. |
|
76 | * <p> |
|
77 | * <Strong>Preconditions</strong>: |
|
78 | * <ul> |
|
79 | * <li> <code>0 <= k <= n </code> (otherwise |
|
80 | * <code>IllegalArgumentException</code> is thrown)</li> |
|
81 | * <li> The result is small enough to fit into a <code>long</code>. The |
|
82 | * largest value of <code>n</code> for which all coefficients are |
|
83 | * <code> < Long.MAX_VALUE</code> is 66. If the computed value exceeds |
|
84 | * <code>Long.MAX_VALUE</code> an <code>ArithMeticException |
|
85 | * </code> is |
|
86 | * thrown.</li> |
|
87 | * </ul> |
|
88 | * |
|
89 | * @param n the size of the set |
|
90 | * @param k the size of the subsets to be counted |
|
91 | * @return <code>n choose k</code> |
|
92 | * @throws IllegalArgumentException if preconditions are not met. |
|
93 | * @throws ArithmeticException if the result is too large to be represented |
|
94 | * by a long integer. |
|
95 | */ |
|
96 | public static long binomialCoefficient(final int n, final int k) { |
|
97 | 140 | if (n < k) { |
98 | 2 | throw new IllegalArgumentException( |
99 | "must have n >= k for binomial coefficient (n,k)"); |
|
100 | } |
|
101 | 138 | if (n < 0) { |
102 | 0 | throw new IllegalArgumentException( |
103 | "must have n >= 0 for binomial coefficient (n,k)"); |
|
104 | } |
|
105 | 138 | if ((n == k) || (k == 0)) { |
106 | 46 | return 1; |
107 | } |
|
108 | 92 | if ((k == 1) || (k == n - 1)) { |
109 | 38 | return n; |
110 | } |
|
111 | ||
112 | 54 | long result = Math.round(binomialCoefficientDouble(n, k)); |
113 | 54 | if (result == Long.MAX_VALUE) { |
114 | 2 | throw new ArithmeticException( |
115 | "result too large to represent in a long integer"); |
|
116 | } |
|
117 | 52 | return result; |
118 | } |
|
119 | ||
120 | /** |
|
121 | * Returns a <code>double</code> representation of the <a |
|
122 | * href="http://mathworld.wolfram.com/BinomialCoefficient.html"> Binomial |
|
123 | * Coefficient</a>, "<code>n choose k</code>", the number of |
|
124 | * <code>k</code>-element subsets that can be selected from an |
|
125 | * <code>n</code>-element set. |
|
126 | * <p> |
|
127 | * <Strong>Preconditions</strong>: |
|
128 | * <ul> |
|
129 | * <li> <code>0 <= k <= n </code> (otherwise |
|
130 | * <code>IllegalArgumentException</code> is thrown)</li> |
|
131 | * <li> The result is small enough to fit into a <code>double</code>. The |
|
132 | * largest value of <code>n</code> for which all coefficients are < |
|
133 | * Double.MAX_VALUE is 1029. If the computed value exceeds Double.MAX_VALUE, |
|
134 | * Double.POSITIVE_INFINITY is returned</li> |
|
135 | * </ul> |
|
136 | * |
|
137 | * @param n the size of the set |
|
138 | * @param k the size of the subsets to be counted |
|
139 | * @return <code>n choose k</code> |
|
140 | * @throws IllegalArgumentException if preconditions are not met. |
|
141 | */ |
|
142 | public static double binomialCoefficientDouble(final int n, final int k) { |
|
143 | 202 | return Math.floor(Math.exp(binomialCoefficientLog(n, k)) + 0.5); |
144 | } |
|
145 | ||
146 | /** |
|
147 | * Returns the natural <code>log</code> of the <a |
|
148 | * href="http://mathworld.wolfram.com/BinomialCoefficient.html"> Binomial |
|
149 | * Coefficient</a>, "<code>n choose k</code>", the number of |
|
150 | * <code>k</code>-element subsets that can be selected from an |
|
151 | * <code>n</code>-element set. |
|
152 | * <p> |
|
153 | * <Strong>Preconditions</strong>: |
|
154 | * <ul> |
|
155 | * <li> <code>0 <= k <= n </code> (otherwise |
|
156 | * <code>IllegalArgumentException</code> is thrown)</li> |
|
157 | * </ul> |
|
158 | * |
|
159 | * @param n the size of the set |
|
160 | * @param k the size of the subsets to be counted |
|
161 | * @return <code>n choose k</code> |
|
162 | * @throws IllegalArgumentException if preconditions are not met. |
|
163 | */ |
|
164 | public static double binomialCoefficientLog(final int n, final int k) { |
|
165 | 18140 | if (n < k) { |
166 | 4 | throw new IllegalArgumentException( |
167 | "must have n >= k for binomial coefficient (n,k)"); |
|
168 | } |
|
169 | 18136 | if (n < 0) { |
170 | 0 | throw new IllegalArgumentException( |
171 | "must have n >= 0 for binomial coefficient (n,k)"); |
|
172 | } |
|
173 | 18136 | if ((n == k) || (k == 0)) { |
174 | 520 | return 0; |
175 | } |
|
176 | 17616 | if ((k == 1) || (k == n - 1)) { |
177 | 496 | return Math.log((double)n); |
178 | } |
|
179 | 17120 | double logSum = 0; |
180 | ||
181 | // n!/k! |
|
182 | 121648084 | for (int i = k + 1; i <= n; i++) { |
183 | 121630964 | logSum += Math.log((double)i); |
184 | } |
|
185 | ||
186 | // divide by (n-k)! |
|
187 | 121630964 | for (int i = 2; i <= n - k; i++) { |
188 | 121613844 | logSum -= Math.log((double)i); |
189 | } |
|
190 | ||
191 | 17120 | return logSum; |
192 | } |
|
193 | ||
194 | /** |
|
195 | * Returns the <a href="http://mathworld.wolfram.com/HyperbolicCosine.html"> |
|
196 | * hyperbolic cosine</a> of x. |
|
197 | * |
|
198 | * @param x double value for which to find the hyperbolic cosine |
|
199 | * @return hyperbolic cosine of x |
|
200 | */ |
|
201 | public static double cosh(double x) { |
|
202 | 16 | return (Math.exp(x) + Math.exp(-x)) / 2.0; |
203 | } |
|
204 | ||
205 | /** |
|
206 | * Returns true iff both arguments are NaN or neither is NaN and they are |
|
207 | * equal |
|
208 | * |
|
209 | * @param x first value |
|
210 | * @param y second value |
|
211 | * @return true if the values are equal or both are NaN |
|
212 | */ |
|
213 | public static boolean equals(double x, double y) { |
|
214 | 2374 | return ((Double.isNaN(x) && Double.isNaN(y)) || x == y); |
215 | } |
|
216 | ||
217 | /** |
|
218 | * Returns n!. Shorthand for <code>n</code> <a |
|
219 | * href="http://mathworld.wolfram.com/Factorial.html"> Factorial</a>, the |
|
220 | * product of the numbers <code>1,...,n</code>. |
|
221 | * <p> |
|
222 | * <Strong>Preconditions</strong>: |
|
223 | * <ul> |
|
224 | * <li> <code>n >= 0</code> (otherwise |
|
225 | * <code>IllegalArgumentException</code> is thrown)</li> |
|
226 | * <li> The result is small enough to fit into a <code>long</code>. The |
|
227 | * largest value of <code>n</code> for which <code>n!</code> < |
|
228 | * Long.MAX_VALUE</code> is 20. If the computed value exceeds <code>Long.MAX_VALUE</code> |
|
229 | * an <code>ArithMeticException </code> is thrown.</li> |
|
230 | * </ul> |
|
231 | * </p> |
|
232 | * |
|
233 | * @param n argument |
|
234 | * @return <code>n!</code> |
|
235 | * @throws ArithmeticException if the result is too large to be represented |
|
236 | * by a long integer. |
|
237 | * @throws IllegalArgumentException if n < 0 |
|
238 | */ |
|
239 | public static long factorial(final int n) { |
|
240 | 24 | long result = Math.round(factorialDouble(n)); |
241 | 22 | if (result == Long.MAX_VALUE) { |
242 | 2 | throw new ArithmeticException( |
243 | "result too large to represent in a long integer"); |
|
244 | } |
|
245 | 20 | return result; |
246 | } |
|
247 | ||
248 | /** |
|
249 | * Returns n!. Shorthand for <code>n</code> <a |
|
250 | * href="http://mathworld.wolfram.com/Factorial.html"> Factorial</a>, the |
|
251 | * product of the numbers <code>1,...,n</code> as a <code>double</code>. |
|
252 | * <p> |
|
253 | * <Strong>Preconditions</strong>: |
|
254 | * <ul> |
|
255 | * <li> <code>n >= 0</code> (otherwise |
|
256 | * <code>IllegalArgumentException</code> is thrown)</li> |
|
257 | * <li> The result is small enough to fit into a <code>double</code>. The |
|
258 | * largest value of <code>n</code> for which <code>n!</code> < |
|
259 | * Double.MAX_VALUE</code> is 170. If the computed value exceeds |
|
260 | * Double.MAX_VALUE, Double.POSITIVE_INFINITY is returned</li> |
|
261 | * </ul> |
|
262 | * </p> |
|
263 | * |
|
264 | * @param n argument |
|
265 | * @return <code>n!</code> |
|
266 | * @throws IllegalArgumentException if n < 0 |
|
267 | */ |
|
268 | public static double factorialDouble(final int n) { |
|
269 | 64 | if (n < 0) { |
270 | 4 | throw new IllegalArgumentException("must have n >= 0 for n!"); |
271 | } |
|
272 | 60 | return Math.floor(Math.exp(factorialLog(n)) + 0.5); |
273 | } |
|
274 | ||
275 | /** |
|
276 | * Returns the natural logarithm of n!. |
|
277 | * <p> |
|
278 | * <Strong>Preconditions</strong>: |
|
279 | * <ul> |
|
280 | * <li> <code>n >= 0</code> (otherwise |
|
281 | * <code>IllegalArgumentException</code> is thrown)</li> |
|
282 | * </ul> |
|
283 | * |
|
284 | * @param n argument |
|
285 | * @return <code>n!</code> |
|
286 | * @throws IllegalArgumentException if preconditions are not met. |
|
287 | */ |
|
288 | public static double factorialLog(final int n) { |
|
289 | 82 | if (n < 0) { |
290 | 2 | throw new IllegalArgumentException("must have n > 0 for n!"); |
291 | } |
|
292 | 80 | double logSum = 0; |
293 | 752 | for (int i = 2; i <= n; i++) { |
294 | 672 | logSum += Math.log((double)i); |
295 | } |
|
296 | 80 | return logSum; |
297 | } |
|
298 | ||
299 | /** |
|
300 | * <p> |
|
301 | * Gets the greatest common divisor of the absolute value of two numbers, |
|
302 | * using the "binary gcd" method which avoids division and modulo |
|
303 | * operations. See Knuth 4.5.2 algorithm B. This algorithm is due to Josef |
|
304 | * Stein (1961). |
|
305 | * </p> |
|
306 | * |
|
307 | * @param u a non-zero number |
|
308 | * @param v a non-zero number |
|
309 | * @return the greatest common divisor, never zero |
|
310 | * @since 1.1 |
|
311 | */ |
|
312 | public static int gcd(int u, int v) { |
|
313 | 528 | if (u * v == 0) { |
314 | 38 | return (Math.abs(u) + Math.abs(v)); |
315 | } |
|
316 | // keep u and v negative, as negative integers range down to |
|
317 | // -2^31, while positive numbers can only be as large as 2^31-1 |
|
318 | // (i.e. we can't necessarily negate a negative number without |
|
319 | // overflow) |
|
320 | /* assert u!=0 && v!=0; */ |
|
321 | 490 | if (u > 0) { |
322 | 366 | u = -u; |
323 | } // make u negative |
|
324 | 490 | if (v > 0) { |
325 | 480 | v = -v; |
326 | } // make v negative |
|
327 | // B1. [Find power of 2] |
|
328 | 490 | int k = 0; |
329 | 526 | while ((u & 1) == 0 && (v & 1) == 0 && k < 31) { // while u and v are |
330 | // both even... |
|
331 | 36 | u /= 2; |
332 | 36 | v /= 2; |
333 | 36 | k++; // cast out twos. |
334 | } |
|
335 | 490 | if (k == 31) { |
336 | 0 | throw new ArithmeticException("overflow: gcd is 2^31"); |
337 | } |
|
338 | // B2. Initialize: u and v have been divided by 2^k and at least |
|
339 | // one is odd. |
|
340 | 490 | int t = ((u & 1) == 1) ? v : -(u / 2)/* B3 */; |
341 | // t negative: u was odd, v may be even (t replaces v) |
|
342 | // t positive: u was even, v is odd (t replaces u) |
|
343 | do { |
|
344 | /* assert u<0 && v<0; */ |
|
345 | // B4/B3: cast out twos from t. |
|
346 | 5214 | while ((t & 1) == 0) { // while t is even.. |
347 | 2082 | t /= 2; // cast out twos |
348 | } |
|
349 | // B5 [reset max(u,v)] |
|
350 | 3132 | if (t > 0) { |
351 | 1378 | u = -t; |
352 | } else { |
|
353 | 1754 | v = t; |
354 | } |
|
355 | // B6/B3. at this point both u and v should be odd. |
|
356 | 3132 | t = (v - u) / 2; |
357 | // |u| larger: t positive (replace u) |
|
358 | // |v| larger: t negative (replace v) |
|
359 | 3132 | } while (t != 0); |
360 | 490 | return -u * (1 << k); // gcd is u*2^k |
361 | } |
|
362 | ||
363 | /** |
|
364 | * Returns an integer hash code representing the given double value. |
|
365 | * |
|
366 | * @param value the value to be hashed |
|
367 | * @return the hash code |
|
368 | */ |
|
369 | public static int hash(double value) { |
|
370 | 1956 | long bits = Double.doubleToLongBits(value); |
371 | 1956 | return (int)(bits ^ (bits >>> 32)); |
372 | } |
|
373 | ||
374 | /** |
|
375 | * For a byte value x, this method returns (byte)(+1) if x >= 0 and |
|
376 | * (byte)(-1) if x < 0. |
|
377 | * |
|
378 | * @param x the value, a byte |
|
379 | * @return (byte)(+1) or (byte)(-1), depending on the sign of x |
|
380 | */ |
|
381 | public static byte indicator(final byte x) { |
|
382 | 10 | return (x >= ZB) ? PB : NB; |
383 | } |
|
384 | ||
385 | /** |
|
386 | * For a double precision value x, this method returns +1.0 if x >= 0 and |
|
387 | * -1.0 if x < 0. Returns <code>NaN</code> if <code>x</code> is |
|
388 | * <code>NaN</code>. |
|
389 | * |
|
390 | * @param x the value, a double |
|
391 | * @return +1.0 or -1.0, depending on the sign of x |
|
392 | */ |
|
393 | public static double indicator(final double x) { |
|
394 | 204 | if (Double.isNaN(x)) { |
395 | 2 | return Double.NaN; |
396 | } |
|
397 | 202 | return (x >= 0.0) ? 1.0 : -1.0; |
398 | } |
|
399 | ||
400 | /** |
|
401 | * For a float value x, this method returns +1.0F if x >= 0 and -1.0F if x < |
|
402 | * 0. Returns <code>NaN</code> if <code>x</code> is <code>NaN</code>. |
|
403 | * |
|
404 | * @param x the value, a float |
|
405 | * @return +1.0F or -1.0F, depending on the sign of x |
|
406 | */ |
|
407 | public static float indicator(final float x) { |
|
408 | 146 | if (Float.isNaN(x)) { |
409 | 2 | return Float.NaN; |
410 | } |
|
411 | 144 | return (x >= 0.0F) ? 1.0F : -1.0F; |
412 | } |
|
413 | ||
414 | /** |
|
415 | * For an int value x, this method returns +1 if x >= 0 and -1 if x < 0. |
|
416 | * |
|
417 | * @param x the value, an int |
|
418 | * @return +1 or -1, depending on the sign of x |
|
419 | */ |
|
420 | public static int indicator(final int x) { |
|
421 | 10 | return (x >= 0) ? 1 : -1; |
422 | } |
|
423 | ||
424 | /** |
|
425 | * For a long value x, this method returns +1L if x >= 0 and -1L if x < 0. |
|
426 | * |
|
427 | * @param x the value, a long |
|
428 | * @return +1L or -1L, depending on the sign of x |
|
429 | */ |
|
430 | public static long indicator(final long x) { |
|
431 | 10 | return (x >= 0L) ? 1L : -1L; |
432 | } |
|
433 | ||
434 | /** |
|
435 | * For a short value x, this method returns (short)(+1) if x >= 0 and |
|
436 | * (short)(-1) if x < 0. |
|
437 | * |
|
438 | * @param x the value, a short |
|
439 | * @return (short)(+1) or (short)(-1), depending on the sign of x |
|
440 | */ |
|
441 | public static short indicator(final short x) { |
|
442 | 10 | return (x >= ZS) ? PS : NS; |
443 | } |
|
444 | ||
445 | /** |
|
446 | * Returns the least common multiple between two integer values. |
|
447 | * |
|
448 | * @param a the first integer value. |
|
449 | * @param b the second integer value. |
|
450 | * @return the least common multiple between a and b. |
|
451 | * @throws ArithmeticException if the lcm is too large to store as an int |
|
452 | * @since 1.1 |
|
453 | */ |
|
454 | public static int lcm(int a, int b) { |
|
455 | 18 | return Math.abs(mulAndCheck(a / gcd(a, b), b)); |
456 | } |
|
457 | ||
458 | /** |
|
459 | * Multiply two integers, checking for overflow. |
|
460 | * |
|
461 | * @param x a factor |
|
462 | * @param y a factor |
|
463 | * @return the product <code>x*y</code> |
|
464 | * @throws ArithmeticException if the result can not be represented as an |
|
465 | * int |
|
466 | * @since 1.1 |
|
467 | */ |
|
468 | public static int mulAndCheck(int x, int y) { |
|
469 | 178 | long m = ((long)x) * ((long)y); |
470 | 178 | if (m < Integer.MIN_VALUE || m > Integer.MAX_VALUE) { |
471 | 16 | throw new ArithmeticException("overflow: mul"); |
472 | } |
|
473 | 162 | return (int)m; |
474 | } |
|
475 | ||
476 | /** |
|
477 | * Round the given value to the specified number of decimal places. The |
|
478 | * value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method. |
|
479 | * |
|
480 | * @param x the value to round. |
|
481 | * @param scale the number of digits to the right of the decimal point. |
|
482 | * @return the rounded value. |
|
483 | * @since 1.1 |
|
484 | */ |
|
485 | public static double round(double x, int scale) { |
|
486 | 28 | return round(x, scale, BigDecimal.ROUND_HALF_UP); |
487 | } |
|
488 | ||
489 | /** |
|
490 | * Round the given value to the specified number of decimal places. The |
|
491 | * value is rounded using the given method which is any method defined in |
|
492 | * {@link BigDecimal}. |
|
493 | * |
|
494 | * @param x the value to round. |
|
495 | * @param scale the number of digits to the right of the decimal point. |
|
496 | * @param roundingMethod the rounding method as defined in |
|
497 | * {@link BigDecimal}. |
|
498 | * @return the rounded value. |
|
499 | * @since 1.1 |
|
500 | */ |
|
501 | public static double round(double x, int scale, int roundingMethod) { |
|
502 | 136 | double sign = indicator(x); |
503 | 136 | double factor = Math.pow(10.0, scale) * sign; |
504 | 136 | return roundUnscaled(x * factor, sign, roundingMethod) / factor; |
505 | } |
|
506 | ||
507 | /** |
|
508 | * Round the given value to the specified number of decimal places. The |
|
509 | * value is rounding using the {@link BigDecimal#ROUND_HALF_UP} method. |
|
510 | * |
|
511 | * @param x the value to round. |
|
512 | * @param scale the number of digits to the right of the decimal point. |
|
513 | * @return the rounded value. |
|
514 | * @since 1.1 |
|
515 | */ |
|
516 | public static float round(float x, int scale) { |
|
517 | 28 | return round(x, scale, BigDecimal.ROUND_HALF_UP); |
518 | } |
|
519 | ||
520 | /** |
|
521 | * Round the given value to the specified number of decimal places. The |
|
522 | * value is rounded using the given method which is any method defined in |
|
523 | * {@link BigDecimal}. |
|
524 | * |
|
525 | * @param x the value to round. |
|
526 | * @param scale the number of digits to the right of the decimal point. |
|
527 | * @param roundingMethod the rounding method as defined in |
|
528 | * {@link BigDecimal}. |
|
529 | * @return the rounded value. |
|
530 | * @since 1.1 |
|
531 | */ |
|
532 | public static float round(float x, int scale, int roundingMethod) { |
|
533 | 136 | float sign = indicator(x); |
534 | 136 | float factor = (float)Math.pow(10.0f, scale) * sign; |
535 | 136 | return (float)roundUnscaled(x * factor, sign, roundingMethod) / factor; |
536 | } |
|
537 | ||
538 | /** |
|
539 | * Round the given non-negative, value to the "nearest" integer. Nearest is |
|
540 | * determined by the rounding method specified. Rounding methods are defined |
|
541 | * in {@link BigDecimal}. |
|
542 | * |
|
543 | * @param unscaled the value to round. |
|
544 | * @param sign the sign of the original, scaled value. |
|
545 | * @param roundingMethod the rounding method as defined in |
|
546 | * {@link BigDecimal}. |
|
547 | * @return the rounded value. |
|
548 | * @since 1.1 |
|
549 | */ |
|
550 | private static double roundUnscaled(double unscaled, double sign, |
|
551 | int roundingMethod) { |
|
552 | 272 | switch (roundingMethod) { |
553 | case BigDecimal.ROUND_CEILING : |
|
554 | 24 | if (sign == -1) { |
555 | 12 | unscaled = Math.floor(unscaled); |
556 | } else { |
|
557 | 12 | unscaled = Math.ceil(unscaled); |
558 | } |
|
559 | 12 | break; |
560 | case BigDecimal.ROUND_DOWN : |
|
561 | 24 | unscaled = Math.floor(unscaled); |
562 | 24 | break; |
563 | case BigDecimal.ROUND_FLOOR : |
|
564 | 24 | if (sign == -1) { |
565 | 12 | unscaled = Math.ceil(unscaled); |
566 | } else { |
|
567 | 12 | unscaled = Math.floor(unscaled); |
568 | } |
|
569 | 12 | break; |
570 | case BigDecimal.ROUND_HALF_DOWN : { |
|
571 | 32 | double fraction = Math.abs(unscaled - Math.floor(unscaled)); |
572 | 32 | if (fraction > 0.5) { |
573 | 16 | unscaled = Math.ceil(unscaled); |
574 | } else { |
|
575 | 16 | unscaled = Math.floor(unscaled); |
576 | } |
|
577 | 16 | break; |
578 | } |
|
579 | case BigDecimal.ROUND_HALF_EVEN : { |
|
580 | 40 | double fraction = Math.abs(unscaled - Math.floor(unscaled)); |
581 | 40 | if (fraction > 0.5) { |
582 | 16 | unscaled = Math.ceil(unscaled); |
583 | 24 | } else if (fraction < 0.5) { |
584 | 8 | unscaled = Math.floor(unscaled); |
585 | } else { |
|
586 | 16 | if (Math.floor(unscaled) / 2.0 == Math.floor(Math |
587 | .floor(unscaled) / 2.0)) { // even |
|
588 | 8 | unscaled = Math.floor(unscaled); |
589 | } else { // odd |
|
590 | 8 | unscaled = Math.ceil(unscaled); |
591 | } |
|
592 | } |
|
593 | 8 | break; |
594 | } |
|
595 | case BigDecimal.ROUND_HALF_UP : { |
|
596 | 88 | double fraction = Math.abs(unscaled - Math.floor(unscaled)); |
597 | 88 | if (fraction >= 0.5) { |
598 | 60 | unscaled = Math.ceil(unscaled); |
599 | } else { |
|
600 | 28 | unscaled = Math.floor(unscaled); |
601 | } |
|
602 | 28 | break; |
603 | } |
|
604 | case BigDecimal.ROUND_UNNECESSARY : |
|
605 | 12 | if (unscaled != Math.floor(unscaled)) { |
606 | 4 | throw new ArithmeticException("Inexact result from rounding"); |
607 | } |
|
608 | break; |
|
609 | case BigDecimal.ROUND_UP : |
|
610 | 24 | unscaled = Math.ceil(unscaled); |
611 | 24 | break; |
612 | default : |
|
613 | 4 | throw new IllegalArgumentException("Invalid rounding method."); |
614 | } |
|
615 | 264 | return unscaled; |
616 | } |
|
617 | ||
618 | /** |
|
619 | * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a> |
|
620 | * for byte value <code>x</code>. |
|
621 | * <p> |
|
622 | * For a byte value x, this method returns (byte)(+1) if x > 0, (byte)(0) if |
|
623 | * x = 0, and (byte)(-1) if x < 0. |
|
624 | * |
|
625 | * @param x the value, a byte |
|
626 | * @return (byte)(+1), (byte)(0), or (byte)(-1), depending on the sign of x |
|
627 | */ |
|
628 | public static byte sign(final byte x) { |
|
629 | 0 | return (x == ZB) ? ZB : (x > ZB) ? PB : NB; |
630 | } |
|
631 | ||
632 | /** |
|
633 | * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a> |
|
634 | * for double precision <code>x</code>. |
|
635 | * <p> |
|
636 | * For a double value <code>x</code>, this method returns |
|
637 | * <code>+1.0</code> if <code>x > 0</code>, <code>0.0</code> if |
|
638 | * <code>x = 0.0</code>, and <code>-1.0</code> if <code>x < 0</code>. |
|
639 | * Returns <code>NaN</code> if <code>x</code> is <code>NaN</code>. |
|
640 | * |
|
641 | * @param x the value, a double |
|
642 | * @return +1.0, 0.0, or -1.0, depending on the sign of x |
|
643 | */ |
|
644 | public static double sign(final double x) { |
|
645 | 328 | if (Double.isNaN(x)) { |
646 | 0 | return Double.NaN; |
647 | } |
|
648 | 328 | return (x == 0.0) ? 0.0 : (x > 0.0) ? 1.0 : -1.0; |
649 | } |
|
650 | ||
651 | /** |
|
652 | * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a> |
|
653 | * for float value <code>x</code>. |
|
654 | * <p> |
|
655 | * For a float value x, this method returns +1.0F if x > 0, 0.0F if x = |
|
656 | * 0.0F, and -1.0F if x < 0. Returns <code>NaN</code> if <code>x</code> |
|
657 | * is <code>NaN</code>. |
|
658 | * |
|
659 | * @param x the value, a float |
|
660 | * @return +1.0F, 0.0F, or -1.0F, depending on the sign of x |
|
661 | */ |
|
662 | public static float sign(final float x) { |
|
663 | 0 | if (Float.isNaN(x)) { |
664 | 0 | return Float.NaN; |
665 | } |
|
666 | 0 | return (x == 0.0F) ? 0.0F : (x > 0.0F) ? 1.0F : -1.0F; |
667 | } |
|
668 | ||
669 | /** |
|
670 | * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a> |
|
671 | * for int value <code>x</code>. |
|
672 | * <p> |
|
673 | * For an int value x, this method returns +1 if x > 0, 0 if x = 0, and -1 |
|
674 | * if x < 0. |
|
675 | * |
|
676 | * @param x the value, an int |
|
677 | * @return +1, 0, or -1, depending on the sign of x |
|
678 | */ |
|
679 | public static int sign(final int x) { |
|
680 | 4 | return (x == 0) ? 0 : (x > 0) ? 1 : -1; |
681 | } |
|
682 | ||
683 | /** |
|
684 | * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a> |
|
685 | * for long value <code>x</code>. |
|
686 | * <p> |
|
687 | * For a long value x, this method returns +1L if x > 0, 0L if x = 0, and |
|
688 | * -1L if x < 0. |
|
689 | * |
|
690 | * @param x the value, a long |
|
691 | * @return +1L, 0L, or -1L, depending on the sign of x |
|
692 | */ |
|
693 | public static long sign(final long x) { |
|
694 | 0 | return (x == 0L) ? 0L : (x > 0L) ? 1L : -1L; |
695 | } |
|
696 | ||
697 | /** |
|
698 | * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a> |
|
699 | * for short value <code>x</code>. |
|
700 | * <p> |
|
701 | * For a short value x, this method returns (short)(+1) if x > 0, (short)(0) |
|
702 | * if x = 0, and (short)(-1) if x < 0. |
|
703 | * |
|
704 | * @param x the value, a short |
|
705 | * @return (short)(+1), (short)(0), or (short)(-1), depending on the sign of |
|
706 | * x |
|
707 | */ |
|
708 | public static short sign(final short x) { |
|
709 | 0 | return (x == ZS) ? ZS : (x > ZS) ? PS : NS; |
710 | } |
|
711 | ||
712 | /** |
|
713 | * Returns the <a href="http://mathworld.wolfram.com/HyperbolicSine.html"> |
|
714 | * hyperbolic sine</a> of x. |
|
715 | * |
|
716 | * @param x double value for which to find the hyperbolic sine |
|
717 | * @return hyperbolic sine of x |
|
718 | */ |
|
719 | public static double sinh(double x) { |
|
720 | 16 | return (Math.exp(x) - Math.exp(-x)) / 2.0; |
721 | } |
|
722 | ||
723 | /** |
|
724 | * Subtract two integers, checking for overflow. |
|
725 | * |
|
726 | * @param x the minuend |
|
727 | * @param y the subtrahend |
|
728 | * @return the difference <code>x-y</code> |
|
729 | * @throws ArithmeticException if the result can not be represented as an |
|
730 | * int |
|
731 | * @since 1.1 |
|
732 | */ |
|
733 | public static int subAndCheck(int x, int y) { |
|
734 | 20 | long s = (long)x - (long)y; |
735 | 20 | if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) { |
736 | 8 | throw new ArithmeticException("overflow: add"); |
737 | } |
|
738 | 12 | return (int)s; |
739 | } |
|
740 | } |