Using BigDecimal

My factorial is hitting a wall, and it is a huge decimal (I put it under 1). How do I use BigDecimal? Here is what I am using to solve these factorials:
    public static double factorial(double n) {
        if      (n <  0)  throw new RuntimeException("Can't be negative stupid.");
        else if (n > 250) throw new RuntimeException("Number too big at the moment! :(");
        else if (n == 0)  return 1;
        else              return (1 / (n * factorial(n-1)));
double z = 200
factorial(z);I get errors because I don't think double can handle something so large. How do I change that snippet of code to BigDecimal, rather how do I use it? The API sort of tells me this is much different from regular number types. Also, can a BigDecimal have a value in the ones or tens place, like 23.839281.... or is it strictly the decimal end, 0.839281... ?
Edited by: kavon89 on Oct 9, 2007 10:49 PM

I gave what the links said a shot, and I need some help debugging:
Here is what worked:
public class Main {
    public static void main(String[] args) {
        solveit();
    public static double factorial(double n) {
        if      (n <  0)  throw new RuntimeException("Can't be negative stupid.");
        else if (n > 100) throw new RuntimeException("Number too big at the moment! :(");
        else if (n == 0)  return 1;
        else              return 1 / (n * factorial(n-1));
    public static void solveit() {
        double z = 2;
        System.out.println(factorial(z));
Here is what I tried to get BigDecimals in there:
public class Main {
    public static void main(String[] args) {
        solveit();
    public static BigDecimal factorial(BigDecimal n) {
        BigDecimal m = new BigDecimal("1");
        n = n.setScale(5);
        return m.divide((n.multiply(factorial(n.subtract(m)))));
    public static void solveit() {
        BigDecimal z = new BigDecimal("2");
        System.out.println(factorial(z)); //1 / 2! == 0.5
}and finally, my error:
Exception in thread "main" java.lang.StackOverflowError
        at java.lang.Character.digit(Character.java:4494)
        at java.lang.Long.parseLong(Long.java:401)
        at java.lang.Long.parseLong(Long.java:461)
        at java.math.BigDecimal.<init>(BigDecimal.java:452)
        at java.math.BigDecimal.<init>(BigDecimal.java:647)
        at Main.factorial(Main.java:23)
        at Main.factorial(Main.java:25)
        at Main.factorial(Main.java:25)
        // the line above this repeats MANY times, and the message ends with...
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)What is wrong? :s Help!
Edited by: kavon89 on Oct 9, 2007 11:43 PM

Similar Messages

  • Using bigdecimal class

    I was using Gregory-Leibniz series to calculate PI = 4 - 4/3 + 4/5 - 4/7 + 4/9 - 4/11 + ...
    Something like:
    double pi = 0.0;      
           int limit = 3000000;      
           for (int i = 0, y = 1; i <= limit; y+=2, i++)
                     if (y == 1)
                          pi = 4;
                   else if (i % 2 == 0)
                          pi += (double)4/y;            
                     else
                          pi -= (double)4/y;                                                   
                     System.out.println(String.format("Loop %d: %.20f", i, pi));                                    }Then I realized PI isn't going to be totally accurate according to IEEE Standard for Binary Floating-Point Arithmetic that java math calculation uses, so I was trying to use BigDecimal class (new to me), this is what I got initally...
             BigDecimal pi = new BigDecimal("0.00");           
              int limit = 3000000;
              for (int i = 0, y = 1; i <= limit; y += 2, i++)
                  if (y == 1)
                          pi = new BigDecimal("4.0");
                   else if (i % 2 == 0)
                          pi = pi.add(new BigDecimal( Double.toString( (double) 4 / y )));
                     else
                          pi = pi.subtract(new BigDecimal( Double.toString( (double) 4 / y )));
                        System.out.println(String.format("Loop %d: %s", i, pi.toString()));                                       
    I realize that when I do the 4/y calculations involving both doubles... the result is probably stored according to the IEEE standards which is the thing to avoid... Is that correct? Is my PI result going to be accurate?
    I noticed with this one decimals up to the 22nd place are all filled with some numbers in the calculations compared with the first one involving only double number calculations which had zero's starting around the 15th decimal.
    Something like doesn't work and ends up with arithmeticexceptions...
    pi = pi.subtract(new BigDecimal("4").divide(new BigDecimal(Integer.toString(y))));
    So I'm actually confused about the right way of using BigDecimal class in this type of calculation to get accurate results. I do realize it's an immutable class and probably a bad idea to use it like this 3 million times in a loop.

    quoting from the API documentation on BigDecimal
    "The BigDecimal class gives its user complete control over rounding behavior. If no rounding mode is specified and the exact result cannot be represented, an exception is thrown; otherwise, calculations can be carried out to a chosen precision and rounding mode by supplying an appropriate MathContext object to the operation."
    That explains the arithmetic exceptions.
    You would be advised to choose your scale first, (that would be the number of decimal places that you want to be using for your calculation. ) Then use the BigDecimal constructors that use the scale value. Construct your BigDecimal 4 outside of the loop so that you are not constructing it over and over again. And finally, read the documentation on how the scale of the result will depend upon the scale of the components going in.
    A little reading and possibly re-reading of the documentation will help in the understanding of the BigDecimal class.

  • Mathematical calculations using BigDecimal

    Hi all,
    I am doing some mathematical calculations using float variables. They are not working properly because of rounding issues....So, before I change the whole program to do the same calculations using BigDecimal, just wanted to check out whether there are any catches in that also. Like, is it safe if I do BigDecimal.add, subract etc. instead of addding the floating point numbers directly.....Can I be assured that the results will be precise, to 2 decimal places?
    Any help will be appreciated...
    Thanks

    The "catch" is that computers do not work with real numbers. They work with representations of real numbers like finite decimals or fractions. My advice is to continue to use doubles, but do not expect infinitely precise results and round the values when outputting them.

  • Determine Number of Decimal Place using BigDecimal

    I was interested to have the following getNumberOfDecimalPlace function :
    System.out.println("0 = " + Utils.getNumberOfDecimalPlace(0)); // 0
    System.out.println("1.0 = " + Utils.getNumberOfDecimalPlace(1.0)); // 0
    System.out.println("1.01 = " + Utils.getNumberOfDecimalPlace(1.01)); // 2
    System.out.println("1.012 = " + Utils.getNumberOfDecimalPlace(1.012)); // 3
    System.out.println("0.01 = " + Utils.getNumberOfDecimalPlace(0.01)); // 2
    System.out.println("0.012 = " + Utils.getNumberOfDecimalPlace(0.012)); // 3
    I use the following code
        public static int getNumberOfDecimalPlace(double value) {
            final BigDecimal bigDecimal = new BigDecimal("" + value);
            final String s = bigDecimal.toPlainString();
            System.out.println(s);
            final int index = s.indexOf('.');
            if (index < 0) {
                return 0;
            return s.length() - 1 - index;
        }However, for case 0, 1.0, it doesn't work well. I expect, "0" as result. But they turned out to be "0.0" and "1.0". This will return "1" as result.
    0.0
    0 = 1
    1.0
    1.0 = 1
    1.01
    1.01 = 2
    1.012
    1.012 = 3
    0.01
    0.01 = 2
    0.012
    0.012 = 3
    Any solution?

    Please [don't cross-post!|http://stackoverflow.com/questions/2296110/determine-number-of-decimal-place-using-bigdecimal], it's considered rude. If you must do it, then at least link each post so that people can find out which answers you've already got in order to avoid duplicate work on our part.
    Please read [_How To Ask Questions The Smart Way_|http://www.catb.org/~esr/faqs/smart-questions.html].

  • Looking for examples using BigDecimal

    Two newbies to Java are looking for examples of code that use the BigDecimal features for rounding and truncating large numbers to more user-friendly values.
    We are doing some hefty math calculations on values defined as doubles and want to round and truncate to within 1/100th for display purposes.
    We've tried some stuff on our own, but it is not cooperating. Any help would be greatly appreciated!

    Here is a good article of how to use BigDecimal
    http://www.javaworld.com/javaworld/jw-06-2001/jw-0601-cents.html
    Hope this helps

  • Exponentail operations using BIGDECIMAL

    hi all
    Can u someone provide me links, notes, codes and suggestions to perform exponential operations using BigDecimal.
    Thankz in advance
    Arun :)

    If you require greater precision than double provides
    and your exponent is integer try
    Google [
    [url=http://www.google.com/search?hl=en&ie=UTF-8&q=squa
    e+and+multiply&btnG=Google+Search]square and
    multiply ]Good point. I forgot the obvious. m^2 = m * m, etc.

  • Rounding using BigDecimal

    Hi all,
    I have read another forum entry about rounding a 2-precision decimal value using BigDecimal, but it does not seem to round when the value =0.5...
    double [] doubleVal = {1.008,1.002,1.005,1.0051};
    for (int i = 0; i < doubleVal.length; i++) {
        double bigDecValUp = new BigDecimal(doubleVal).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
    System.out.println("Round of " + doubleVal[i] + ": Up " + bigDecValUp);
    Output:
    Round of 1.008: Up 1.01
    Round of 1.002: Up 1.0
    Round of 1.005: Up 1.0
    Round of 1.0051: Up 1.01
    Shouldn't the third entry (1.005) also round up to 1.01? If so, how could I fix this?
    Thanks,
    Phil

    the observed rounding is correct, considering that the exact value of the double precision presentation of 1.005 is 1.004999..> print(new BigDecimal(1.005));
    1.00499999999999989341858963598497211933135986328125to get the result you want don't pass the value as a double but as a string....> print(new BigDecimal("1.005"));
    1.005

  • Floats using BigDecimal

    I am trying to float my answer using BigDecimal, anyone have any suggestions? PLease Help.
    import java.lang.reflect.*;
    import java.awt.*;
    import java.io.*;
    import java.math.*;
    class myMean
              public float myMean(float x)     
                   float result = 0;     
                   result = (x += result);
                   return (result);     
    class MethodCalls
         public static void main(String[] args) throws IOException
              // declarations
              BufferedReader in = new BufferedReader (new InputStreamReader(System.in));
              myMean out = new myMean();     
              String sArraySize, strgrade, strdecimal;                    
              double size =2;
              float score = 0, tracker = 0;      
              float FloatConversion;
              float callAverageMethod;
              int x= 0;
              System.out.println("Please enter the number of tests to average:");
              sArraySize = in.readLine();           
              size = Double.parseDouble(sArraySize);      
              System.out.println("Please enter the amount of decial places to use:");
              strdecimal = in.readLine();
              x = Integer.parseInt(strdecimal);
              for (float counter=0; counter < size; counter++)     
                   // input on the test scores come here          
                   System.out.print("What is the score of the " + (counter+1) + " test: ");
                   strgrade = in.readLine();
                   score = Float.parseFloat(strgrade);
                   tracker += score ;          
              callAverageMethod = out.myMean(tracker);
              System.out.println();      
              BigDecimal bd = new BigDecimal(callAverageMethod);
    bd = bd.setScale(x, BigDecimal.ROUND_UP);
              System.out.println(" The average score of the " + size + " tests is: " + bd/size);
    }

    Try doing the computation ( sum / num grades ) within the BigDecimal. If you create the BigDecimal and then do the integer division, you'll create a new double that isn't subject to the rounding.
    public class bdtest {
        public bdtest() {
        public static void main(String[] args) {
            float f = 100.0f;
            int n = 6;
            BigDecimal bd = new BigDecimal( f / n );
            bd = bd.setScale( 2, BigDecimal.ROUND_UP );
            System.out.println( bd );
    }

  • Cannot use BigDecimal fields

    Hello
    I'm using CR inside Rational Application Developer 7.0 with POJO datasources.
    When i try to use POJO with java.math.BigDecimal field, this field doesn't show up in the Crystal Report designer.
    It seems to be a bug, may something has to be done to import these BigDecimal ?
    See you
    Sébastien

    <p> A demo version of Crystal Reports Developer edition is available here:</p><p><a href="http://www.businessobjects.com/products/reporting/crystalreports/default.asp" target="_blank">  http://www.businessobjects.com/products/reporting/crystalreports/default.asp</a></p><p>Ted Ueda <br /></p>

  • How to pass BigDecimal as currecny to Crystal Reports using JRC 11

    Im using JRC to load and view crystal reports.ie loading crystal reports that are created (not by me) using Crystal Reports v 10. My work is just load those rpt files using JRC thick client.
    rpt files are bound to .mdb (MS Access) database and DB is password protected.  One of the table in database has currency data type. I'm creating a POJO class to implement the table structure. To match with Currency type, Im using BigDecimal type in my pojo class. when i open the .rpt file in crystal report designer, it shows with default currency symbol (i.e $ and  £) But the when i load the same report via JRC, It doesnot show the symbol at all.
    When I change this to String and pass symbol, it is coming up properly. But in some places, the reports use sum function of 2 curency fields. So in this case, string cannot be used.
    Any help would be appreciated.
    Thanks.

    Sorry. I did not get your point directly.
    So I'd recommend not directly relying on internal handling of BigDecimal. You can still report off the value.
    So you are telling me not to use BigDecimal? If not what should I use? Please be bit more explanative.
    Thanks.

  • Bigdecimal as PrimaryKey Type in Entity

    Hi,
       I am using Netweaver CE 7.1 for deploying a test application. My Entity has a Bigdecimal field as Primary key. While deploying the applcation I am getting following exception :
    <b>
    Primary Keys Check: Primary key 'actRmatId' of class 'entity.Activities' cannot be of type 'java.math.BigDecimal'. Allowed types are: Java primitive types; any primitive wrapper type; java.lang.String; java.util.Date; java.sql.Date; byte[], file: TestEJB.jar#META-INF/persistence.xml, column 0, line 0, severity: error</b>
      Can anybody please tell me, why Bigdecimal is restricted in this version of netweaver while it was working fine in NetWeaver Application Server, Java(TM) EE 5 Edition...
      My Application is using Bigdecimal because of the precision requirements. Is there a way to use Entities with Bigdecimal  as primary key types in CE7.1.
    Thanks ,
    Prasoon.

    Hi Prasoon,
    with CE 7.1, we introduced a check that asserts that the IDs obey the +recomendations +expressed by the JPA specification § 2.1.4:
    +The primary key (or field or property of a composite primary key) should be one of the following types:
    any Java primitive type; any primitive wrapper type; java.lang.String; java.util.Date;
    java.sql.Date. In general, however, approximate numeric types (e.g., floating point types) should
    never be used in primary keys. Entities whose primary keys use types other than these will not be portable.
    If generated primary keys are used, only integral types will be portable. If java.util.Date is
    used as a primary key field or property, the temporal type should be specified as DATE.+
    This check rejects BigDecimal fields. It is probably to strict. We will likely lift the restriction with the next release.
    Unfortunately, I am not aware of any workaround to disable the check.
    Best regards,
    Adrian Görler

  • BigDecimal division

    HI All,
    I want to use the Bigdecimal logic for dividing the by 100 in message Mapping.
    How can i achive this..Is there any documentation is available? or anybody can tell me how can i use bigdecimal for  division?
    REgards
    Venkatesh

    Convert the string to BigDecimal and use division available for BigDecimal and then convert the result to String if needed
    this is simple and can be easily done using BigDecimal Class use API for the same
    http://java.sun.com/j2se/1.4.2/docs/api/java/math/BigDecimal.html
    Rajesh

  • Incorrect arithmetic in bigdecimal

    Hello,
    I attempting to do some simple arithmetic (for FX rate conversion) using BigDecimal that is generating incorrect results (while the same calculation with double works correctly).
    Can someone please take a look at this sample program and tell me what I may be doing wrong? Or, at least provide some insight into what is going wrong so that I can take steps to avoid?
    import static java.math.RoundingMode.HALF_UP;
    import java.math.BigDecimal;
    import java.math.MathContext;
    public class BigDecimalTest {
          public static void main(String[] args) {
                // 15,000,000,000,000
                BigDecimal large_value = new BigDecimal("15000000000000");
                MathContext mc = new MathContext(16, HALF_UP);
                BigDecimal divisor = new BigDecimal("1.5");
                BigDecimal numerator = BigDecimal.ONE.divide(divisor, mc);
                BigDecimal resultOne = large_value.multiply(numerator);
                BigDecimal resultTwo = large_value.divide(divisor, mc);
                System.out.println("Big Decimal arithmetic:");
                System.out.println("15 trillion * (1/1.5) = ["+resultOne.toPlainString()+"]");
                System.out.println("15 trillion / 1.5 = ["+resultTwo.toPlainString()+"]");
                System.out.println("results compare as ["+resultOne.compareTo(resultTwo)+"]\n");
                double large_dbl_value = 15000000000000d;
                double divisorDbl = 1.5;
                double resultOneDbl = large_dbl_value * (1/divisorDbl);
                double resultTwoDbl = large_dbl_value / divisorDbl;
                System.out.println("double arithmetic:");
                System.out.println("15 trillion * (1/1.5) = ["+resultOneDbl+"]");
                System.out.println("15 trillion /1.5 = ["+resultTwoDbl+"]");
                System.out.println("results compare as ["+(resultOneDbl - resultTwoDbl)+"]");
    }Thank you,
    Ed Bridges

    When I look more into the proposed solution -- for example in the code below -- I still see discrepancies in the arithmetic of BigDecimal and double:
    import static java.math.RoundingMode.HALF_UP;
    import java.math.BigDecimal;
    import java.math.MathContext;
    public class BigDecimalTest {
         public static void main(String[] args) {
              // 12,345,678,901,234
              BigDecimal large_value = new BigDecimal("12345678901234");
              MathContext mc = new MathContext(16, HALF_UP);
              for (int i = 80; i< 90; i++) {           
                   BigDecimal rate = new BigDecimal(i).divide(new BigDecimal("100.0"));
                   BigDecimal divisor = rate.setScale(16, HALF_UP);
                   BigDecimal numerator = divisor.pow(-1, mc);
                   BigDecimal resultOne = large_value.multiply(numerator).round(mc);
                   BigDecimal resultTwo = large_value.divide(divisor, mc);
                   if (resultOne.compareTo(resultTwo)!= 0) {
                        System.out.println("Big Decimal arithmetic:");
                        System.out.println(large_value + " * (1/" + rate + ") = ["+resultOne.toPlainString()+"]");
                        System.out.println(large_value + " / " + rate + " = ["+resultTwo.toPlainString()+"]");
                        System.out.println("results compare as ["+resultOne.compareTo(resultTwo)+"]\n");
              double large_dbl_value = 12345678901234d;
              for (int i = 80; i< 90; i++) {           
                   double divisorDbl = i / 100;
                   double resultOneDbl = large_dbl_value * (1/divisorDbl);
                   double resultTwoDbl = large_dbl_value / divisorDbl;
                   if (resultOneDbl != resultTwoDbl) {
                        System.out.println("double arithmetic:");
                        System.out.println(large_dbl_value + " * (1/" + divisorDbl + ") = ["+resultOneDbl+"]");
                        System.out.println(large_dbl_value + " / " + divisorDbl + " = ["+resultTwoDbl+"]");
                        System.out.println("results compare as ["+(resultOneDbl - resultTwoDbl)+"]");
    }This produces the following result:
    Big Decimal arithmetic:
    12345678901234 * (1/0.86) = [14355440582830.24]
    12345678901234 / 0.86 = [14355440582830.23]
    results compare as [1]
    Big Decimal arithmetic:
    12345678901234 * (1/0.89) = [13871549327229.22]
    12345678901234 / 0.89 = [13871549327229.21]
    results compare as [1]It's these "off-by-one penny" errors that are killing me :-(

  • BigDecimal Rounding

    I am trying to use BigDecimal to rounding a double number with a ROUND_HALF_UP mode.
    my codes is:
    public static double tryRound(double vl, int decimal) {
    BigDecimal bd = new BigDecimal(vl);
    bd = bd.setScale(decimal, BigDecimal.ROUND_HALF_UP);
    return bd.doubleValue();
    public static void test() {
    System.out.println(tryRound(1233.55, 1));
    System.out.println(tryRound(1233.555, 2));
    System.out.println(tryRound(1233.5555, 3));
    System.out.println(tryRound(1233.555555, 4));
    and I got a result of:
    1233.5
    1233.56
    1233.555
    1233.5556
    Does anybody know why it can't round rightly?
    Any messages is helpful.
    Thanks!
    Gordon

    because internally none of the numbers you have are precise. try this instead:         public static double tryRound(String vl, int decimal) {
                             BigDecimal bd = new BigDecimal(vl);
                             bd = bd.setScale(decimal, BigDecimal.ROUND_HALF_UP);
                             return bd.doubleValue();
             public static void test() {
                      System.out.println(tryRound("1233.55", 1));
                      System.out.println(tryRound("1233.555", 2));
                      System.out.println(tryRound("1233.5555", 3));
                      System.out.println(tryRound("1233.555555", 4));
             }

  • BigDecimal vs floating points...

    Hi all,
    I know its probably been asked amillion times before but I need to finally fully understand and get my head around the two.
    Firstly here are some bits I've been told by different people and read in different places (alot of people seem to think differently which is what confuses me):
    - I've read that if you are wanting precision for currency for example that floating point shouldnt be used because of its accuracy down to the fact it cant represent every decimal number.
    - The some people have told me that it doesnt matter and theres not much point ,ost the time in BigDecimal all you need to do is correct the floating point with formatting.
    - I've asked about this before but people just seem to give me a short answer to it but without actually explaining why or where they get it from, you cant just assume an answer based on nothing...
    I'm building some engineering software that has a general accuracy of 3 decmial places (millimeters from meters) and my first thought is that if currency at 2 decimal places requires BigDecimal then I surely require it (I cant afford to be missing off mm for every calculation, theres alot!) but the problem is this has resulted in me building pretty much the whole application with BigDecimal which you can probably imagine brings up thoughts about performance and memory uptake, I do calculations with BigDecimal, store data in BigDecimal and infact the only thing I do in double is the graphical display as the accuracy isnt so important.
    My last question is if this is an ok way to build an accurate application it makes me start to wonder why is floating points used more than BigDecimals, surely most numbers are required to be accurate in applications especially of an enterprise scale?
    Thanks,
    Ken

    MarksmanKen wrote:
    So your a big user of BigDecimal as well then? Thats good to know someone else thinks in similar ways, I was starting to feel like abit of an idiot for using them so extensively lolNot at all. The idiots are the people who use primitives rather than BigDecimal "because they're faster" even though they've never actually experienced any performance problems. Of course, there are lots of cases where the speed of a primitive is preferable, but on the whole those guys know perfectly well who they are and what they're doing.
    My program is very calculation heavy and I've not had any real performance issues yet but I was wondering if the performance gain would be significant enough while keeping the accuracy.Testing will show you the way. Don't let any "we tested this calculation a million times using primitives and the same one using BigDecimal, and it showed a remarkable 3 seconds quicker using primitives" sidetrack you, either. All that matters is that your actual production code is performant enough for your application. Generally speaking, anything involving currency will probably be better using BigDecimal, or, really, a Money class which happens to use BigDecimal under the covers. Quite why enterprise-targeted languages don't have some sort of native Money or Currency class out-of-the-box remains a mystery, to be honest.

Maybe you are looking for

  • OSB 10gR3 - Process WS-Security flag not working with PasswordDigest

    Hi, By Oracle documentation when you set the "process ws-security header" in security section of a proxy service, the proxy service act as an active intermediary and consume the ws-security header received in inbound messages. This feature works fine

  • Looping login screen in Crystal Reports for Visual Studio 2008

    Hello, I am using Visual Studio 2008 with the Crystal Reports Basic for Visual Studio 2008. Visual Studio and the Crystal Reports Basic Runtime for Visual Studio 2008 (x64) are installed on both the development and production boxes.  I am using Cryst

  • JSException without a message

    Within my applet I get the following exception when I call JSObject win = JSObject.getWindow(myApplet); Exception in thread "AWT-EventQueue-2" netscape.javascript.JSException      at netscape.javascript.JSObject.getWindow(Unknown Source) Since there

  • Ipod shuffle 3rd generation

    My friend gave me his iPod shuffle 3rd generation so that I could delete the music he has on it and sync it with my iTunes library instead. When I plug it into my computer's USB port, it charges but does not appear in my devices on iTunes. How do I g

  • Scan Options Window

    Hi, I have the DeskJet 3050a and when I scan something it automatically scans as a JPEG. As I wish to  edit my scans I have downloaded and installed the  software for OCR ( I have followed the instructions posted on the  HP support forum, installing