1

For this formula:

formula

I had to make a method to automate it, and I've received 4 examples to try it out.

x = 1 > p = 2

x = 3 > p = -226

x = 4 > p = 9854

however, when I insert 11 the answer should be 3.0198773447 and I receive -1.78316945E8 instead :/

here is my code:

System.out.println("Insira o numero: ");
    int x = input.nextInt();
    int fat = 1;
   int contador = 0;
   int contador1 = 0;
   double p  = 0;
  for(double i = 1; i <=x; i++){
    fat = 1;
    contador++;
    contador1 = contador* 2;
    for(double j = 1; j <= contador1; j++){
      fat *=j;

    }
    if(contador <=1){
      p += fat / contador;
    }
    if(contador % 2 ==0 && contador > 1){ 
    p += fat / contador;
    }else if( contador % 2 != 0 && contador > 1){
      p -= fat / contador;
    }
  }
  System.out.println(p);
Spektre
  • 49,595
  • 11
  • 110
  • 380
fennekinho
  • 11
  • 2
  • Each term in the series is an integer, therefore the series will always be integer valued. Therefore x = 11 will not give you 3.0198773447, it will give an integer which I calculate as -101939302914483595906. – President James K. Polk Aug 18 '22 at 19:37
  • 1
    you do not need to iterate the nested for loop from 1 but from last amount instead of computing the same factorials again and again, you should keep the subresult of `(2i)!/i` as small as possible to not overflow/round too soon... its basicaly the same as in here (see the second half of this answer:) [My program for calculating pi using Chudnovsky in C++ precision problem](https://stackoverflow.com/a/73258767/2521214) – Spektre Aug 19 '22 at 02:00
  • also as @PresidentJamesK.Polk suggest the series is integer only, you obviously used floating point `double` with 53 bits of mantissa which got rounded once you hit numbers above `(2^53)-1` however you should not have any digits after decimal point so where did the `3.0198773447` come from? Or You have the equation wrong and it should be `P = 1/2! + 2/4! - ... i/(2i)!` however that leads to `~0.4244` instead. – Spektre Aug 20 '22 at 08:19

1 Answers1

1

If you type in 11, that means contador1 will become as high as 22 (you will loop 11 times, every loop you first increment contador, and contador1 is twice that, so, 22. In other words, you'll end up having to calculate 22!.

The int type does not hold any arbitrary integer. It can only hold integers between -2^31 and +2^31-1. If you try to go beyond those bounds, it just loops around. Witness it in action:

int x = Integer.MAX_VALUE; // a constant representing 2^31-1.
int y = x + 1;
System.out.println(x);
System.out.println(y);

// Prints: 2147483647
//        -2147483648

Where'd that minus come from? That's that whole 'loops around' thing. 22! is much lager than than this upper bound. Hence, your code doesn't work and it also explains why your algorithm tosses a negative number in there.

You could choose to use long instead which can hold it, but long, too, has limits - 2^63-1 to be precise. You could use double which goes ever further (up to about 1e308 which is a lot more than 2^63), but doubles are not accurate and the lack of accuracy gets worse as you move further away from 0. Past 2^53 or so, the distance between 2 representable numbers in the double range is more than 1, meaning, +1 no longer does anything (all operations on double values are rounded to the nearest representable double after every operation).

More generally trying to do 'math' on really large numbers is a non-trivial affair, and your basic + and / can no longer get the job done. Look up the API of BigDecimal which guarantees you perfect accuracy at the cost of, naturally, performance. You could use that, and get perfect answers. Though it'll take a while.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72