Path: blob/master/test/jdk/java/math/BigDecimal/AddTests.java
41152 views
/*1* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 6362557 820069826* @summary Some tests of add(BigDecimal, mc)27* @author Joseph D. Darcy28*/2930import java.math.*;31import static java.math.BigDecimal.*;32import java.util.Set;33import java.util.EnumSet;3435public class AddTests {3637private static Set<RoundingMode> nonExactRoundingModes =38EnumSet.complementOf(EnumSet.of(RoundingMode.UNNECESSARY));3940/**41* Test for some simple additions, particularly, it will test42* the overflow case.43*/44private static int simpleTests() {45int failures = 0;4647BigDecimal[] bd1 = {48new BigDecimal(new BigInteger("7812404666936930160"), 11),49new BigDecimal(new BigInteger("7812404666936930160"), 12),50new BigDecimal(new BigInteger("7812404666936930160"), 13),51};52BigDecimal bd2 = new BigDecimal(new BigInteger("2790000"), 1);53BigDecimal[] expectedResult = {54new BigDecimal("78403046.66936930160"),55new BigDecimal("8091404.666936930160"),56new BigDecimal("1060240.4666936930160"),57};58for (int i = 0; i < bd1.length; i++) {59if (!bd1[i].add(bd2).equals(expectedResult[i]))60failures++;61}62return failures;63}6465/**66* Test for extreme value of scale and rounding precision that67* could cause integer overflow in right-shift-into-sticky-bit68* computations.69*/70private static int extremaTests() {71int failures = 0;7273failures += addWithoutException(valueOf(1, -Integer.MAX_VALUE),74valueOf(2, Integer.MAX_VALUE), null);75failures += addWithoutException(valueOf(1, -Integer.MAX_VALUE),76valueOf(-2, Integer.MAX_VALUE), null);77return failures;78}7980/**81* Print sum of b1 and b2; correct result will not throw an82* exception.83*/84private static int addWithoutException(BigDecimal b1, BigDecimal b2, MathContext mc) {85if (mc == null)86mc = new MathContext(2, RoundingMode.DOWN);8788try {89BigDecimal sum = b1.add(b2, mc);90printAddition(b1, b2, sum.toString());91return 0;92} catch(ArithmeticException ae) {93printAddition(b1, b2, "Exception!");94return 1;95}96}9798/**99* Test combinations of operands that may meet the condensation100* criteria when rounded to different precisions.101*/102private static int roundingGradationTests() {103int failures = 0;104105failures += roundAway(new BigDecimal("1234e100"),106new BigDecimal( "1234e97"));107108failures += roundAway(new BigDecimal("1234e100"),109new BigDecimal( "1234e96"));110111failures += roundAway(new BigDecimal("1234e100"),112new BigDecimal( "1234e95"));113114failures += roundAway(new BigDecimal("1234e100"),115new BigDecimal( "1234e94"));116117failures += roundAway(new BigDecimal("1234e100"),118new BigDecimal( "1234e93"));119120failures += roundAway(new BigDecimal("1234e100"),121new BigDecimal( "1234e92"));122123failures += roundAway(new BigDecimal("1234e100"),124new BigDecimal("1234e50"));125126127failures += roundAway(new BigDecimal("1000e100"),128new BigDecimal( "1234e97"));129130failures += roundAway(new BigDecimal("1000e100"),131new BigDecimal( "1234e96"));132133failures += roundAway(new BigDecimal("1000e100"),134new BigDecimal( "1234e95"));135136failures += roundAway(new BigDecimal("1000e100"),137new BigDecimal( "1234e94"));138139failures += roundAway(new BigDecimal("1000e100"),140new BigDecimal( "1234e93"));141142failures += roundAway(new BigDecimal("1000e100"),143new BigDecimal( "1234e92"));144145failures += roundAway(new BigDecimal("1000e100"),146new BigDecimal("1234e50"));147148149150failures += roundAway(new BigDecimal("1999e100"),151new BigDecimal( "1234e97"));152153failures += roundAway(new BigDecimal("1999e100"),154new BigDecimal( "1234e96"));155156failures += roundAway(new BigDecimal("1999e100"),157new BigDecimal( "1234e95"));158159failures += roundAway(new BigDecimal("1999e100"),160new BigDecimal( "1234e94"));161162failures += roundAway(new BigDecimal("1999e100"),163new BigDecimal( "1234e93"));164165failures += roundAway(new BigDecimal("1999e100"),166new BigDecimal( "1234e92"));167168failures += roundAway(new BigDecimal("1999e100"),169new BigDecimal("1234e50"));170171172173failures += roundAway(new BigDecimal("9999e100"),174new BigDecimal( "1234e97"));175176failures += roundAway(new BigDecimal("9999e100"),177new BigDecimal( "1234e96"));178179failures += roundAway(new BigDecimal("9999e100"),180new BigDecimal( "1234e95"));181182failures += roundAway(new BigDecimal("9999e100"),183new BigDecimal( "1234e94"));184185failures += roundAway(new BigDecimal("9999e100"),186new BigDecimal( "1234e93"));187188failures += roundAway(new BigDecimal("9999e100"),189new BigDecimal( "1234e92"));190191failures += roundAway(new BigDecimal("9999e100"),192new BigDecimal("1234e50"));193194return failures;195}196197private static void printAddition(BigDecimal b1, BigDecimal b2, String s) {198System.out.println("" + b1+ "\t+\t" + b2 + "\t=\t" + s);199}200201private static int roundAway(BigDecimal b1, BigDecimal b2) {202int failures = 0;203204b1.precision();205b2.precision();206207BigDecimal b1_negate = b1.negate();208BigDecimal b2_negate = b2.negate();209210b1_negate.precision();211b2_negate.precision();212213failures += roundAway1(b1, b2);214failures += roundAway1(b1, b2_negate);215failures += roundAway1(b1_negate, b2);216failures += roundAway1(b1_negate, b2_negate);217218return failures;219}220221private static int roundAway1(BigDecimal b1, BigDecimal b2) {222int failures = 0;223failures += roundAway0(b1, b2);224failures += roundAway0(b2, b1);225return failures;226}227228/**229* Compare b1.add(b2, mc) with b1.add(b2).round(mc) for a variety230* of MathContexts.231*/232private static int roundAway0(BigDecimal b1, BigDecimal b2) {233int failures = 0;234BigDecimal exactSum = b1.add(b2);235236for(int precision = 1 ; precision < exactSum.precision()+2; precision++) {237for(RoundingMode rm : nonExactRoundingModes) {238MathContext mc = new MathContext(precision, rm);239BigDecimal roundedExactSum = exactSum.round(mc);240241try {242BigDecimal sum = b1.add(b2, mc);243244if (!roundedExactSum.equals(sum) ) {245failures++;246System.out.println("Exact sum " + exactSum +247"\trounded by " + mc +248"\texpected: " + roundedExactSum + " got: ");249printAddition(b1, b2, sum.toString());250}251// else {252// System.out.print(mc + "\t");253// printAddition(b1, b2, sum.toString());254// }255256} catch (ArithmeticException ae) {257printAddition(b1, b2, "Exception!");258failures++;259}260}261}262263return failures;264}265266/**267* Verify calling the precision method should not change the268* computed result.269*/270private static int precisionConsistencyTest() {271int failures = 0;272MathContext mc = new MathContext(1,RoundingMode.DOWN);273BigDecimal a = BigDecimal.valueOf(1999, -1); //value is equivalent to 19990274275BigDecimal sum1 = a.add(BigDecimal.ONE, mc);276a.precision();277BigDecimal sum2 = a.add(BigDecimal.ONE, mc);278279if (!sum1.equals(sum2)) {280failures ++;281System.out.println("Unequal sums after calling precision!");282System.out.print("Before:\t");283printAddition(a, BigDecimal.ONE, sum1.toString());284285System.out.print("After:\t");286printAddition(a, BigDecimal.ONE, sum2.toString());287}288289return failures;290}291292private static int arithmeticExceptionTest() {293int failures = 0;294BigDecimal x;295try {296//297// The string representation "1e2147483647", which is equivalent298// to 10^Integer.MAX_VALUE, is used to create an augend with an299// unscaled value of 1 and a scale of -Integer.MAX_VALUE. The300// addend "1" has an unscaled value of 1 with a scale of 0. The301// addition is performed exactly and is specified to have a302// preferred scale of max(-Integer.MAX_VALUE, 0). As the scale303// of the result is 0, a value with Integer.MAX_VALUE + 1 digits304// would need to be created. Therefore the next statement is305// expected to overflow with an ArithmeticException.306//307x = new BigDecimal("1e2147483647").add(new BigDecimal(1));308failures++;309} catch (ArithmeticException ae) {310}311return failures;312}313314public static void main(String argv[]) {315int failures = 0;316317failures += extremaTests();318failures += roundingGradationTests();319failures += precisionConsistencyTest();320failures += arithmeticExceptionTest();321322if (failures > 0) {323throw new RuntimeException("Incurred " + failures +324" failures while testing rounding add.");325}326}327}328329330