Stuck with calculating exponents in Java (Taylor Series) [duplicate] - java

This question already has answers here:
pow (x,y) in Java
(4 answers)
Closed 6 years ago.
I'm a bit stumped. I'm working on a homework question that requires you to find e^x through a series of 30 iterations: 1 + x + x^2/2! ... x^n/n!. In this case n = 30 and the range for x is -3 through 3. Seems straightforward enough. However when trying to execute it in Java I'm finding that I'm baffled.
The thought was to run two for loops. The outer loop for the iterations of x and the inner loop for the iterations for n. Here is the code so far:
double series = 1.0;
for (int x=-3; x<=3; x++)
{
for (int n=1; n<=x+30; n++)
{
series = series + (x^n)/n;
n*=n;
}
System.out.println(""+ x +"\t "+ (series+1));
}
Any advice would be greatly appreciated.

You might have to pay more attention to every single variable and the value changes inside the loops to better verify your code.
You have done a few mistakes:
multiplied n to itself and then divided by n as well. According to your formula you need to power the number by n, not nFactorial. Moreover nFactorial is a large number to be stored (and get accurate results), better use the advantage of dividing by n and multiplying by x at every step (see below code).
You have also used the XOR operator. Instead use the Math.pow() method.
You need to initialize the series value in each inner loop start.
If you started with initial value of 1, do not need to print (series+1) at end. Better initialize it to 0, or remove +1 in the print.
The following code would solve your purpose better.
double series = 1.0;
double term = 1.0;
for (int x = -3; x <= 3; x++) {
series = 1.0;
term = 1.0;
for (int n = 1; n <= 30; n++) {
term = (term * x / n);
series += term;
}
System.out.println("" + x + "\t " + (series));
}

you can write your formula with MATH.POW like this:
for (int x=-3; x<=3; x++)
{
for (int n=1; n<=x+30; n++)
{
series = series + (Math.pow(x,n)/n);
n*=n;
}
System.out.println(""+ x +"\t "+ (series+1));
}

Related

for X terms, find P = (2! /1) + (!4/2) - (!6/3) ... and my code works for every test but one

For this 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);
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.

Most efficient way to compute a polynomial

Polynomial: a0x^0 + a1x^1 +a2x^2 + a3x^3 + ... + anx^n
Array: array_a[] = {a0, a1, a2, a3 ... an};
I wrote a function to calculate this polynomial in Java:
public double cal(double x) {
double y = 0.0;
for (int index = array_a.length - 1; index >= 0; index--) {
y = array_a[index] + y * x;
}
return y;
}
This seems 5 times faster than the loop y += array_a[index] * Math.Pow(x, index);
But I wondering if there is a better way to compute this polynomial?
** For anyone thinks it's a different calculation: I did test the function above. It does the same thing with y += array_a[index] * Math.Pow(x, index); and they compute the same result.
Thanks.
This is Horner's method. If you only want to calculate it once per polynomial, this is the most efficient algorithm:
… Horner's method requires only n additions and n multiplications, and its storage requirements are only n times the number of bits of x. …
Horner's method is optimal, in the sense that any algorithm to evaluate an arbitrary polynomial must use at least as many operations. Alexander Ostrowski proved in 1954 that the number of additions required is minimal. Victor Pan proved in 1966 that the number of multiplications is minimal.
If you need to evaluate the polynomial extremely many times and the degree is very high, then there are methods to transform the representation of the polynomial (preconditioning) so that the number of multiplication is reduced to ⌊n/2⌋ + 2. This seems not very practical though, at least I've never seen this in the wild. I've found an online paper that describes some of the algorithms if you are interested.
Also mentioned in the paper, due to the CPU architecture it might be more efficient if you evaluating even and odd terms separately so they can be placed in parallel pipelines:
public double cal(double x) {
double x2 = x * x;
double y_odd = 0.0, y_even = 0.0;
int index = array_a.length - 1;
if (index % 2 == 0) {
y_even = array_a[index];
index -= 1;
}
for (; index >= 0; index -= 2) {
y_odd = array_a[index] + y_odd * x2;
y_even = array_a[index-1] + y_even * x2;
}
return y_even + y_odd * x;
}
The JIT/compiler might be able to do this conversion for you or even use SIMD to make it very fast automagically. Anyway, for this kind of micro-optimization, always profile before committing to a final solution.

Java For-loop changes numeric result when changing type of loop variable

I wrote a program to calculate the PI number with Leibniz formula:
[
I wrote a for-loop with type of initialization is "int" , the loop works fine but when i changed the initialization type to "long" the result is changed. This only happens when the loop times over a billion. This makes the "int - loop" calculates PI more accurate than "long - loop". I don't know why this happens. Please help me to understand this issue. Thanks! and here is my code.
public static void main(String[] args) {
double result1 = 0;
double result2 = 0;
double sign = 1;
for (int i = 0; i <= 1607702095; i++) {
result1 += sign/(2 * i + 1);
sign *= -1;
}
sign = 1;
for (long j = 0; j <= 1607702095; j++) {
result2 += sign/(2 * j + 1);
sign *= -1;
}
System.out.println("result1 " + result1 * 4);
System.out.println("result2 " + result2 * 4);
System.out.println("pi " + Math.PI);
}
And the result is:
result1 3.141592653576877
result2 3.1415926529660116
pi 3.141592653589793
Actually, your first loop would have int overflow in the calculation of (2 * i + 1) when i is large enough, so I wouldn't rely on the output of it.
The second loop, on the other hand, produces a more correct output, since (2 * j + 1) doesn't overflow, since it performs long multiplication.
This makes the "int - loop" calculates PI more accurate than "long - loop"
That's probably just a coincidence, since the calculations in the int loop overflow.
Because you are getting overflow at the line
result1 += sign/(2 * i + 1);
Where the value of 2*i cross the max integer value
int range is -2,147,483,648 to 2,147,483,647 but when you do 2*i for greater value it crosses that range.
Better to be stick with long and that gives you correct output.
2 * i when i is close to the end of your loop will overflow the max value for an int which is 2147483647.
Using a long that operation doesn't overflow.
The correct procedure is using a long type. Probably because values are added and removed around the correct PI for some strange behavior the overflows momentarily compute to a value closer to the right PI.
I suppose that change the limit of the for loop of few values will change the final result to a value that is more far from the right PI.
You have integer overflow.
The max capacity of a signed int is (2^31)-1, or 2,147,483,647.
(1,607,702,095 * 2) is 3215404190, which is bigger than 2,147,483,647.
When you change i to a long you increase the capacity of i to (2^63)-1.
Noticed everyone is pointig the integer overflow, but you might want a solution. (If you already have one, please ignore the following :) )
Having the overflow in the (2 * i + 1) part of the code, you should max the i in the for loop to (Integer.MAX_VALUE / 2 - 1), which results in:
for (int i = 0; i <= (Integer.MAX_VALUE / 2 - 1); i++) {
result1 += sign/(2 * i + 1);
sign *= -1;
}
You can also do that to the long part with (Long.MAX_VALUE / 2 - 1) but it will be running for a VERY LONG time.

Problems with dividing while using for loop

For some reason whenever I try to run this code, speed remains at 0 and it counts i up to x and then speed is suddenly changed to 1.0. speed is supposed to be a decimal of x depending on how many times the for-loop has run through. I don't understand why this is happening and would be very grateful for some clarity.
double speed;
int x = 200;
for(int i = 0; i <= x; i++){
speed = i/x;
System.out.println("Speed- " + speed);
System.out.println("Ticks- " + i);
}
for(int i = x; i >= 0; i--){
speed = i/x;
System.out.println("Speed- " + speed);
System.out.println("Ticks- " + i);
}
Try this:
double x = 200; // use a double instead of an int
The problem? you were dividing two ints, and the result is another int. By converting one of the two operands to a double, the division will now yield a number with decimals.
x must be an float variable in order to get the correct result. If both, i and x are integers, speed is an integer too, and that's the reason you get only 0 and 1

Sum of factorials

So I need to output a sum of factorials like 1!+2!...+n!=sum I found a way to get a single factorial but I don't know how to sum them together. This is my attempt at doing so:
System.out.println("Ievadiet ciparu");
Scanner in = new Scanner(System.in);
n = in.nextInt();
if ( n < 0 )
System.out.println("Ciparam jabut pozitivam.");
else
{
while (x>2){
for ( c = 1 ; c <= n ; c++ )
fact = fact*c;
sum=sum+fact;
n=n-1;
if (n==0) break;
}
System.out.println("Faktorialu summa "+sum);
Rather than have a loop 1-n and calculate each factorial elsewhere, I would accumulate the sum as you calculate the factorials - ie have two local variables; one for factorial and one for the sum:
long factorial = 1, sum = 0;
for (int i = 1; i <= n; i++) {
factorial *= i;
sum += factorial;
}
When tested with n = 5, sum is 153, which is correct: 1 + 2 + 6 + 24 + 120
Your problem was that the sum was outside the loop - you just needed braces like here.
Also, your while loop condition x < 2 will never change, so either the loop will never execute (if x > 1) or the loop will never terminate, because x is not changed within the loop.
hmmm my search for finding a recursive(via recursive method calling) version of these code still getting nowhere
`public static long factorialSum(long n){
long x = n;
for(int i = 1; i < n; i++){
x = (n-i)*(1+x);
}
return x;
}`
if you just look at the problem more closely you'll see you can do it in linear time, the trick is in (n-1)! + n! = (n-1)!*(1 + n), to understand this more deeply i recommend add (n-2)! just to see how it grows.

Categories

Resources