0

I've created an android app that calculates the factorial of an input number. My code is:

void factorial(int x){
    if(x>=0){
        BigInteger res= new BigInteger("1");
        for(int i=x; i>1; i--){
            res = res.multiply(BigInteger.valueOf(i));
        }

        TextView text = (TextView)findViewById(R.id.resultTextView);
        text.setText(res.toString());
    }
}

It works but when I try calculating factorial 80.000 and more the app stucks for a moment and then exits, reloading the graphical 'desktop' inteface of android. The same piece of code run by a pc creates no problems. How can I fix my app to calculate those values rather than terminate itself?

Thank's in advance.

Vivek Barai
  • 1,338
  • 13
  • 26
Nick
  • 241
  • 1
  • 2
  • 10
  • 1
    First I would suggest you to find out why the app got killed/crashes. I'm not an Android dev, but I would suspect that you are calculating it in a wrong place. As calculating factorial of 80000 takes a while I would do it in some background process which won't block the view. – Admit Dec 15 '17 at 13:56
  • @Admit How do you suggest creating this background process? – Nick Dec 15 '17 at 13:57
  • 1
    a Thread more than a Process – Blackbelt Dec 15 '17 at 13:58
  • @Nick, I suspect that Admit suggest you use your google skills to find out about Android AsyncTasks or threading. – 323go Dec 15 '17 at 13:58
  • @323go To tell the truth I am rookie and I don't understand what you tell me aim for. What about Android AsyncTasks? What am I supposed to troubleshoot with that? – Nick Dec 15 '17 at 14:02
  • @Nick actually another thing might be that the value is too big for your TextView. I'd recommend you to debug your application to understand where is the point of failure. If it's the calculation or the Android part (TextView) – Admit Dec 15 '17 at 14:07
  • @Admint Can you suggest me a better way to display it? – Nick Dec 15 '17 at 14:10
  • @Nick I think TextView is fine. You might need to configure it properly. Just make sure you find the place where is fails. If you don't know how to debug an Android app. Try to remove the TextView part and see if it still fails. – Admit Dec 15 '17 at 14:22
  • I don't know why you are trying to compute this on a mobile device. According to Wolfram Alpha, 80k factorial will have around 400k digits... – Iulian Popescu Dec 15 '17 at 14:24
  • If you find out that the issue is the TextView. I would suggest you to close this question and ask another solely about TextView. – Admit Dec 15 '17 at 14:24
  • @IulianPopescu 357507 to be precise – Admit Dec 15 '17 at 14:26
  • I would bet on a memory exception, rather on some problem with the `TextView` – Iulian Popescu Dec 15 '17 at 14:29
  • @IulianPopescu The point is I cant see why a pc with Netbeans can calculate 100000 or more as I use the same algorithm – Nick Dec 15 '17 at 14:31
  • Because even though mobile devices have pretty good specs, there is still a big gap between them and PCs. – Iulian Popescu Dec 15 '17 at 14:35

3 Answers3

2

Try this:

private class FactCalculator extends AsyncTask<Void, Void, BigInteger> {
    int number = 0;

    public FactCalculator(int i) {
        this.number =i;
    }

    @Override
    protected BigInteger doInBackground(final Void... params){
        try{
            if(number>=0) {
                BigInteger res = new BigInteger("1");
                for (int i = number; i > 1; i--) {
                    res = res.multiply(BigInteger.valueOf(i));
                }
                return res;
            }
         } catch(Exception e){
             e.printStackTrace();
         }
         return null;
     }

     @Override
     protected void onPostExecute(final BigInteger result) {
         if (result != null) {
             TextView text = (TextView)findViewById(R.id.resultTextView);
             text.setText(result.toString());
         }
     }
 }

Call it like:

new FactCalculator(80000).execute();

Note:- As others have pointed out in the comments it may be because the value is too large, there may be memory issues or to hold in a String or in the TextView,

Nongthonbam Tonthoi
  • 12,667
  • 7
  • 37
  • 64
  • I'm sorry but I rookie. Where do I have to paste the piece of code you mention? – Nick Dec 15 '17 at 14:14
  • @Nick make it an inner class of your activity class – Nongthonbam Tonthoi Dec 15 '17 at 14:15
  • Thank you for your code. It started calculating 80000 without freezing the screen but I guess it crashes down because it can't display it. Can you suggest me how to tackle with it? – Nick Dec 15 '17 at 14:21
  • I guess I'll have it save the value for me rather than displaying when it's too large. Thank you. Is there any way to know if the value is too large for the particular resource capabilities of the device where I try it? – Nick Dec 15 '17 at 14:24
  • @Nick I think the capacity depends on how much memory your device can allocate, although String has also limits for the number of characters it can hold. You need to do some logic to show it in chunks, maybe in multiple pages – Nongthonbam Tonthoi Dec 15 '17 at 14:31
1

Calculating factorials lead to very big numbers very fast. The factorial of 100 is 9.332621544 E+157. Your factorial is 3.097722251 E+357506! Although BigInteger theoretically has no limitations, I will suggest you to read the answer in this question. Also BigInteger is an immutable class, so creating new ones in every loop is really heavy on your memory. Your code seems correct, but when you deal with factorials most of the times you fall into memory problems.

Dimitris
  • 560
  • 3
  • 17
0

you can put your method in handler

    Handler handler=new Handler(); 
    handler.post(new Runnable(){ 
    @Override
    public void run() {
        if(x>=0){
          ................
        }
        handler.postDelayed(this,500);
    }
});