Path: blob/master/test/jdk/java/math/BigDecimal/ZeroScalingTests.java
41149 views
/*1* Copyright (c) 2003, 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 4902952 4905407 4916149 805779326* @summary Tests that the scale of zero is propagated properly and has the27* proper effect and that setting the scale to zero does not mutate the28* BigDecimal.29* @author Joseph D. Darcy30*/3132import java.math.*;33import java.util.*;3435public class ZeroScalingTests {3637static MathContext longEnough = new MathContext(50, RoundingMode.UNNECESSARY);3839static BigDecimal[] zeros = new BigDecimal[23];40static {41for(int i = 0; i < 21; i++) {42zeros[i] = new BigDecimal(BigInteger.ZERO, i-10);43}44zeros[21] = new BigDecimal(BigInteger.ZERO, Integer.MIN_VALUE);45zeros[22] = new BigDecimal(BigInteger.ZERO, Integer.MAX_VALUE);46}4748static BigDecimal element = BigDecimal.valueOf(100, -2);4950static MathContext contexts[] = {51new MathContext(0, RoundingMode.UNNECESSARY),52new MathContext(100, RoundingMode.UNNECESSARY),53new MathContext(5, RoundingMode.UNNECESSARY),54new MathContext(4, RoundingMode.UNNECESSARY),55new MathContext(3, RoundingMode.UNNECESSARY),56new MathContext(2, RoundingMode.UNNECESSARY),57new MathContext(1, RoundingMode.UNNECESSARY),58};596061static int addTests() {62int failures = 0;6364for(BigDecimal zero1: zeros) {65for(BigDecimal zero2: zeros) {66BigDecimal expected = new BigDecimal(BigInteger.ZERO,67Math.max(zero1.scale(), zero2.scale()));68BigDecimal result;6970if(! (result=zero1.add(zero2)).equals(expected) ) {71failures++;72System.err.println("For classic exact add, expected scale of " +73expected.scale() + "; got " +74result.scale() + ".");75}7677if(! (result=zero1.add(zero2, MathContext.UNLIMITED)).equals(expected) ) {78failures++;79System.err.println("For UNLIMITED math context add," +80" expected scale of " +81expected.scale() + "; got " +82result.scale() + ".");83}8485if(! (result=zero1.add(zero2, longEnough)).equals(expected) ) {86failures++;87System.err.println("For longEnough math context add," +88" expected scale of " +89expected.scale() + "; got " +90result.scale() + ".");91}9293}94}9596// Test effect of adding zero to a nonzero value.97for (MathContext mc: contexts) {98for (BigDecimal zero: zeros) {99if (Math.abs((long)zero.scale()) < 100 ) {100101int preferredScale = Math.max(zero.scale(), element.scale());102if (mc.getPrecision() != 0) {103if (preferredScale < -4 )104preferredScale = -4;105else if (preferredScale > -(5 - mc.getPrecision())) {106preferredScale = -(5 - mc.getPrecision());107}108}109110111/*112System.err.println("\n " + element + " +\t" + zero + " =\t" + result);113114System.err.println("scales" + element.scale() + " \t" + zero.scale() +115" \t " + result.scale() + "\t precison = " + mc.getPrecision());116System.err.println("expected scale = " + preferredScale);117*/118119BigDecimal result = element.add(zero, mc);120if (result.scale() != preferredScale ||121result.compareTo(element) != 0) {122failures++;123System.err.println("Expected scale " + preferredScale +124" result scale was " + result.scale() +125" ; value was " + result);126}127128result = zero.add(element, mc);129if (result.scale() != preferredScale ||130result.compareTo(element) != 0) {131failures++;132System.err.println("Expected scale " + preferredScale +133" result scale was " + result.scale() +134" ; value was " + result);135}136137result = element.negate().add(zero, mc);138if (result.scale() != preferredScale ||139result.compareTo(element.negate()) != 0) {140failures++;141System.err.println("Expected scale " + preferredScale +142" result scale was " + result.scale() +143" ; value was " + result);144}145146result = zero.add(element.negate(), mc);147if (result.scale() != preferredScale ||148result.compareTo(element.negate()) != 0) {149failures++;150System.err.println("Expected scale " + preferredScale +151" result scale was " + result.scale() +152" ; value was " + result);153}154155}156}157}158159return failures;160}161162static int subtractTests() {163int failures = 0;164165for(BigDecimal zero1: zeros) {166for(BigDecimal zero2: zeros) {167BigDecimal expected = new BigDecimal(BigInteger.ZERO,168Math.max(zero1.scale(), zero2.scale()));169BigDecimal result;170171if(! (result=zero1.subtract(zero2)).equals(expected) ) {172failures++;173System.err.println("For classic exact subtract, expected scale of " +174expected.scale() + "; got " +175result.scale() + ".");176}177178if(! (result=zero1.subtract(zero2, MathContext.UNLIMITED)).equals(expected) ) {179failures++;180System.err.println("For UNLIMITED math context subtract," +181" expected scale of " +182expected.scale() + "; got " +183result.scale() + ".");184}185186if(! (result=zero1.subtract(zero2, longEnough)).equals(expected) ) {187failures++;188System.err.println("For longEnough math context subtract," +189" expected scale of " +190expected.scale() + "; got " +191result.scale() + ".");192}193194}195}196197198// Test effect of adding zero to a nonzero value.199for (MathContext mc: contexts) {200for (BigDecimal zero: zeros) {201if (Math.abs((long)zero.scale()) < 100 ) {202203int preferredScale = Math.max(zero.scale(), element.scale());204if (mc.getPrecision() != 0) {205if (preferredScale < -4 )206preferredScale = -4;207else if (preferredScale > -(5 - mc.getPrecision())) {208preferredScale = -(5 - mc.getPrecision());209}210}211212213/*214System.err.println("\n " + element + " +\t" + zero + " =\t" + result);215216System.err.println("scales" + element.scale() + " \t" + zero.scale() +217" \t " + result.scale() + "\t precison = " + mc.getPrecision());218System.err.println("expected scale = " + preferredScale);219*/220221BigDecimal result = element.subtract(zero, mc);222if (result.scale() != preferredScale ||223result.compareTo(element) != 0) {224failures++;225System.err.println("Expected scale " + preferredScale +226" result scale was " + result.scale() +227" ; value was " + result);228}229230result = zero.subtract(element, mc);231if (result.scale() != preferredScale ||232result.compareTo(element.negate()) != 0) {233failures++;234System.err.println("Expected scale " + preferredScale +235" result scale was " + result.scale() +236" ; value was " + result);237}238239result = element.negate().subtract(zero, mc);240if (result.scale() != preferredScale ||241result.compareTo(element.negate()) != 0) {242failures++;243System.err.println("Expected scale " + preferredScale +244" result scale was " + result.scale() +245" ; value was " + result);246}247248result = zero.subtract(element.negate(), mc);249if (result.scale() != preferredScale ||250result.compareTo(element) != 0) {251failures++;252System.err.println("Expected scale " + preferredScale +253" result scale was " + result.scale() +254" ; value was " + result);255}256257}258}259}260261return failures;262}263264static int multiplyTests() {265int failures = 0;266267BigDecimal ones[] = {268BigDecimal.valueOf(1, 0),269BigDecimal.valueOf(10, 1),270BigDecimal.valueOf(1000, 3),271BigDecimal.valueOf(100000000, 8),272};273274List<BigDecimal> values = new LinkedList<BigDecimal>();275values.addAll(Arrays.asList(zeros));276values.addAll(Arrays.asList(ones));277278for(BigDecimal zero1: zeros) {279for(BigDecimal value: values) {280BigDecimal expected = new BigDecimal(BigInteger.ZERO,281(int)Math.min(Math.max((long)zero1.scale()+value.scale(),282Integer.MIN_VALUE ),283Integer.MAX_VALUE ) );284BigDecimal result;285286if(! (result=zero1.multiply(value)).equals(expected) ) {287failures++;288System.err.println("For classic exact multiply, expected scale of " +289expected.scale() + "; got " +290result.scale() + ".");291}292293if(! (result=zero1.multiply(value, MathContext.UNLIMITED)).equals(expected) ) {294failures++;295System.err.println("For UNLIMITED math context multiply," +296" expected scale of " +297expected.scale() + "; got " +298result.scale() + ".");299}300301if(! (result=zero1.multiply(value, longEnough)).equals(expected) ) {302failures++;303System.err.println("For longEnough math context multiply," +304" expected scale of " +305expected.scale() + "; got " +306result.scale() + ".");307}308309}310}311312return failures;313}314315static int divideTests() {316int failures = 0;317318BigDecimal [] ones = {319BigDecimal.valueOf(1, 0),320BigDecimal.valueOf(10, -1),321BigDecimal.valueOf(100, -2),322BigDecimal.valueOf(1000, -3),323BigDecimal.valueOf(1000000, -5),324};325326for(BigDecimal one: ones) {327for(BigDecimal zero: zeros) {328BigDecimal expected = new BigDecimal(BigInteger.ZERO,329(int)Math.min(Math.max((long)zero.scale() - one.scale(),330Integer.MIN_VALUE ),331Integer.MAX_VALUE ) );332BigDecimal result;333334if(! (result=zero.divide(one)).equals(expected) ) {335failures++;336System.err.println("For classic exact divide, expected scale of " +337expected.scale() + "; got " +338result.scale() + ".");339}340341if(! (result=zero.divide(one, MathContext.UNLIMITED)).equals(expected) ) {342failures++;343System.err.println("For UNLIMITED math context divide," +344" expected scale of " +345expected.scale() + "; got " +346result.scale() + ".");347}348349if(! (result=zero.divide(one, longEnough)).equals(expected) ) {350failures++;351System.err.println("For longEnough math context divide," +352" expected scale of " +353expected.scale() + "; got " +354result.scale() + ".");355}356357}358}359360return failures;361}362363static int setScaleTests() {364int failures = 0;365366int scales[] = {367Integer.MIN_VALUE,368Integer.MIN_VALUE+1,369-10000000,370-3,371-2,372-1,3730,3741,3752,3763,37710,37810000000,379Integer.MAX_VALUE-1,380Integer.MAX_VALUE381};382383for(BigDecimal zero: zeros) {384for(int scale: scales) {385try {386BigDecimal bd = zero.setScale(scale);387}388catch (ArithmeticException e) {389failures++;390System.err.println("Exception when trying to set a scale of " + scale +391" on " + zero);392}393}394}395396return failures;397}398399static int toEngineeringStringTests() {400int failures = 0;401402String [][] testCases = {403{"0E+10", "0.00E+12"},404{"0E+9", "0E+9"},405{"0E+8", "0.0E+9"},406{"0E+7", "0.00E+9"},407408{"0E-10", "0.0E-9"},409{"0E-9", "0E-9"},410{"0E-8", "0.00E-6"},411{"0E-7", "0.0E-6"},412};413414for(String[] testCase: testCases) {415BigDecimal bd = new BigDecimal(testCase[0]);416String result = bd.toEngineeringString();417418if (!result.equals(testCase[1]) ||419!bd.equals(new BigDecimal(result))) {420failures++;421System.err.println("From input ``" + testCase[0] + ",'' " +422" bad engineering string output ``" + result +423"''; expected ``" + testCase[1] + ".''");424}425426}427428return failures;429}430431static int ulpTests() {432int failures = 0;433434for(BigDecimal zero: zeros) {435BigDecimal result;436BigDecimal expected = BigDecimal.valueOf(1, zero.scale());437438if (! (result=zero.ulp()).equals(expected) ) {439failures++;440System.err.println("Unexpected ulp value for zero value " +441zero + "; expected " + expected +442", got " + result);443}444}445446return failures;447}448449static int setScaleDoesNotMutateTest() {450BigDecimal total = new BigDecimal("258815507198903607775511093103396443816569106750031264155319238473795838680758514810110764742309284477206138527975952150289602995045050194333030191178778772026538699925775139201970526695485362661420908248887297829319881475178467494779683293036572059595504702727301324759997409522995072582369210284334718757260859794972695026582432867589093687280300148141501712013226636373167978223780290547640482160818746599330924736802844173226042389174403401903999447463440670236056324929325189403433689"451+ ".426167432065785331444814035799717606745777287606858873045971898862329763544687891847664736523584843544347118836628373041412918374550458884706686730726101338872517021688769782894793734049819222924171842793485919753186993388451909096042127903835765393729547730953942175461146061715108701615615142134282261293656760570061554783195726716403304101469782303957325142638493327692352838806741611887655695029948975509680496573999174402058593454203190963443179532640446352828089016874853634851387762579319853267317320515941105912189838719919259277721994880193541634872882180184303434360412344059435559680494807415573269199203376126242271766939666939316648575065702750502798973418978204972336924254702551350654650573582614211506856383897692911422458286912085339575875324832979140870119455620532272318122103640233069115700020760625493816902806241630788230268031695140687964931377988962507263990468276009750998066442971308866347136022907166625330623130307555914930120150437900510530537258665172619821272937026713977709974434967165159545592482710663639966781678268622620229577009317698254134914742098420792313931843709810905414336383757407675429663714210967924767434203021205270369316797752411974617662200898086335322218191674846795163102021505555508444216708745911194321674887527227200297039471799580744303346354057273540730643842091810899490590914195225087593013834388801018488174855060306804024894292757613618190472234110859436472645203753139820658279559340251226992556744343475086923568365637919479462424794554522865559888240039662899509652221329892034706445253487898044421278283079233226845124525434586324657471286953226255430662125870993375281512713207125720748163498642795960457639954616530163959004770092547297392499137383176609646505351001304840762905826237024982330597805063521162285806541220110524989649256399233792799406995068469271941269511818994954109392839548141262324660472253632382325038836831429045617036015122388070240133760858500132713255407855625837956886349324981003917084922808187223285051144454915441134217743066575863563572152133978905444998209075763950909784148142018992367290485890072303179512881131769414783097454103103347826517701720263541869335631166977965013552647906729408522950996105479525445916501155305220090853891226367184989434453290788068397817927893708837722255115237672194162924260945492012622891770365546831236789867922136747819364833843397165107825773447549885351449899330007200651144003961228091210630807333236718793283427788965479074476288255387824982443633190938302785760754436525586544523339170400053128503337395428393881357669568532722167493096151221381017320147344991331421789379785964440840684363041795410525097564979585773948558651896834067324427900848255265001498890329859444233861478388742393060996236783742654761350763876989363052609107226398858310051497856931093693697981165801539060516895227818925342535261227134364063673285588256280386915163875872231395348293505967057794409379709079685798908660258077792158532257603211711587587586356431658240229896344639704");452if (total.setScale(0, RoundingMode.DOWN).equals(total.setScale(0, RoundingMode.DOWN))) {453return 0;454} else {455return 1;456}457}458459public static void main(String argv[]) {460int failures = 0;461462failures += addTests();463failures += subtractTests();464failures += multiplyTests();465failures += divideTests();466failures += setScaleTests();467failures += toEngineeringStringTests();468failures += ulpTests();469failures += setScaleDoesNotMutateTest();470471if (failures > 0 ) {472throw new RuntimeException("Incurred " + failures + " failures" +473" testing the preservation of zero scales.");474}475}476}477478479