Java Recursion over 2 parameters and in two directions - java

I wish to recurse over two parameters simultaneously in a generic way. Here some explanation:
This is how the function calls should look like Func(int a, int b):
Call 0: Func(0, 0)
Call 1: Func(0, 1)
Call 1: Func(1, 0)
Call 1: Func(0, -1)
Call 1: Func(-1, 0)
How would I implement this in code, ensuring the following statements:
All possible combinations of a INRANGE (-INF, INF) and b INRANGE (-INF, INF) are considered.
There is no overhead, with that I mean that the same function is not used several times in the recursion.
I later want to expand it to do the same thing over 7 parameters.
Regards.

Here's my take on the spiral approach:
// this is your function
static void func(int x, int y)
{
System.out.println("x = "+x+", y = "+y);
}
// this calls func for all possible combinations of signs of the variables in arr
static void allPossibleSigns(int pos, Integer... arr)
{
if (pos == arr.length)
{
func(arr[0], arr[1]); // not really generic
}
else
{
allPossibleSigns(pos+1, arr);
arr[pos] = -arr[pos];
if (arr[pos] != 0)
allPossibleSigns(pos+1, arr);
}
}
static void caller()
{
for (int t = 0; t < MAX; t++)
for (int x = 0; x <= t; x++)
{
int y = (t-x);
allPossibleSigns(0, x, y);
}
}
If you want something more generic than func(arr[0], arr[1]);, you can replace it with:
Method[] methods = NewMain.class.getMethods();
for (Method m: methods)
{
if (m.getName().equals("func"))
m.invoke(null, arr);
}
and add some error checking. I used Integer... instead of int... in printAllPossibleSigns because of this approach (the above doesn't work for int...). This assumes you only have one function called func. If this is not the case, you'll have to add some additional checks.
For MAX = 4, it prints:
x = 0, y = 0
x = 0, y = 1
x = 0, y = -1
x = 1, y = 0
x = -1, y = 0
x = 0, y = 2
x = 0, y = -2
x = 1, y = 1
x = 1, y = -1
x = -1, y = -1
x = -1, y = 1
x = 2, y = 0
x = -2, y = 0
x = 0, y = 3
x = 0, y = -3
x = 1, y = 2
x = 1, y = -2
x = -1, y = -2
x = -1, y = 2
x = 2, y = 1
x = 2, y = -1
x = -2, y = -1
x = -2, y = 1
x = 3, y = 0
x = -3, y = 0
How this will be extended to 3 variable may not entirely be clear, so here's caller for 3 variables:
static void caller()
{
for (int t = 0; t < MAX; t++)
for (int x = 0; x <= t; x++)
for (int y = 0; y <= (t-x); y++)
{
int z = (t-x-y);
printAllPossibleSigns(0, x, y, z);
}
}
And that's about all you have to change, along with your function, obviously, and func(arr[0], arr[1]); if you didn't choose the generic approach.

I propose a spiral, non-recursively easiest.
For ease of reading the move is selected again in every step.
int x = 0;
int y = 0;
for (int t = 0; t < 100; ++t) {
func(x, y);
if (x <= 0 && y == 0) { // Widen spiral.
--x;
++y; // So next condition takes next.
} else if (x < 0 && y >= 0) { // Left, upper quadrant.
++x;
++y;
} else if (x >= 0 && y > 0) { // Right, upper.
++x;
--y;
} else if (x >= 0 && y <= 0) { // Right, lower.
--x;
--y;
} else if (x < 0 && y < 0) { // Left, lower.
--x;
++y;
} else {
throw new IllegalStateException("x = " + x + ", y = " + y);
}
}
I did not try the code! Check the conditions.

Maybe some knowledge of combinatorics would help here. To me this looks like you have a set of elements from -N to to +N. Now you want to call a function with for each variation of length == 7 those elements.
Such a range may be really big. Depending on the cost of the operation you want to call this might take longer than you live.
I would write an Iterator which delivers a new variation of the elements (which are your function parameters) on each call of next().
The implementation of such an iterator could you BigInteger, if you need big numbers. You could use an Array or List and change it's elements on each iteration. If you search for combinatorial algorithms or permutation / variation algorithms you might find details and maybe even implementations.
Another (similar) way (with more overhead, I think) would be to use just one number (e.g. a BigInteger) to mark the current variation. On each iteration you add 1 to this variation index number.
To get your parameters from this number you must perform a base transformation on this variation index. The base will be the number of elements in your elements set. The resulting number's digits each have the range of 0 to the number of elements -1. From this you can use each digit to get the parameters for your function call from the list of elements.
I did than some time ago and it works fine. Can't promise than I can find it.

For n dimensions:
Below I use positive numbers for coordinates. For every positive (greater 0) coordinate in a solution making the coordinate negative also is a solution (almost factor 2^n solutions more). (Using positive numbers simplifies the reading of a solution.)
This is a solutions for a coordinate vector of dimension n. The coordinates are chosen with ever growing "radius" = sum of coordinates.
static void func(int[] x) {
System.out.printf("%s%n", Arrays.toString(x));
}
/**
* Call many funcs with several coordinates.
* #param x n-dimensional coordinates.
* #param fromI starting index for variable coordinates.
* #param r radius, equal to the sum of x[>= fromIndex].
* #param t downward counter limiting the number of calls.
* #return new value of t.
*/
static int callFuncsForRadius(int[] x, int fromIndex, int r, int t) {
if (t <= 0) {
return t;
}
if (fromIndex >= x.length) { // Nothing more to vary.
if (r == 0) { // Read radius sum.
func(x);
--t;
}
return t;
}
for (int rNext = r; rNext >= 0; --rNext) {
x[fromIndex] = rNext;
t = callFuncsForRadius(x, fromIndex + 1, r - rNext, t);
if (t <= 0) {
break;
}
}
return t;
}
static int callFuncs(int[] x, int t) {
int r = 0;
while (t > 0) {
t = callFuncsForRadius(x, 0, r, t);
++r;
}
return t;
}
public static void main(String[] args) {
int n = 3;
int[] x = new int[n];
int t = 10; // N^n, where N = 2^31.
callFuncs(x, t);
}

Related

Recursion to normal loop convert

I have a method that is actually counting someValues.The Method is given below.
public static double sum(int z, int x, int y)
{
double count = 0.0;
if (x == 0)
{
if (z <= 0) return 1.0;
return 0.0;
}
for (int i = 1; i <= y; i++)
{
count += sum(z - i, x - 1, y);
}
return count;
}
I just want to convert this method from recursion to normal iteration. Or if possible to some one line equation. Please help me.
So this is not pretty, but it works without recursion. Also i changed the return type from double to int because of reasons:
public static int sum(int z, int x, int y)
{
// Compute number of calls
int[][] calls = new int[x+1][x*y+1];
calls[0][0] = 1;
for (int i = 0; i < x; i++) {
for (int j = 0; j <= x*y; j++) {
for (int target = j+1; target <= j+y && target <= x*y; target++) {
calls[i+1][target] += calls[i][j];
}
}
}
// Return count of last column where z <= 0
int result = 0;
for (int j = x*y; z-j <= 0; j--) {
result += calls[x][j];
}
return result;
}
To understand, have a look at this high-tech Excel sheet:
This chart illustrates a call of sum(3, 3, 3). Horizontally you see x and vertically you see z both get smaller. y is 3 and not changed.
The top left 1 means one call to sum(3, 3, 3). This call then spawns three child calls (because of y=3): sum(2, 2, 3), sum(1, 2, 3) and sum(0, 2, 3). These three calls are found in the next column (where x=2).
Each of those three calls then spawns again three calls, shown in the row of x=1. These nine calls overlap a bit regarding z. Each of those nine calls then spawns again three calls, resulting in 27 calls in the x=0 column.
To get the result, you simply count all calls in the x=0 column, where z <= 0. In this example this is every call, so you get a result of 27. For a larger z the result would be smaller.
public static double sum(int z, int x, int y) {
int num = 0;
for (int i = 0; i <= y; i++) {
if (z - x - i > 0) {
num++;
}
}
return (double) (Math.pow(y, x) - num);
}
Explanation: your method launches at most y^x recursive calls. On the last level of recursion, where x == 0, you have to determine the max value of z throughout all the calls and check how many of these calls do have z > 0, so that the call returns 0 and you do not have to take it into account. Now, on the last level of recursion, the max value of z is given by z - x. You now simply count all the instances in the for loop for which z - x stays positive so it does not influence your sum. After you computed that number, substract it from the initial approximation of the result, which was y^x.

increasing code performance of codility

today i heard about this website called codility where a user can give various programming test to check their code's performance.
When I started, they presented me with this sample test,
Task description A small frog wants to get to the other side of the
road. The frog is currently located at position X and wants to get to
a position greater than or equal to Y. The small frog always jumps a
fixed distance, D. Count the minimal number of jumps that the small
frog must perform to reach its target.
Write a function:
class Solution { public int solution(int X, int Y, int D); }
that, given three integers X, Y and D, returns the minimal number of jumps from position X to a position equal to or greater than Y.
For example,
given:
X = 10
Y = 85
D = 30 the function should return 3,
because the frog will be positioned as follows:
after the first jump,
at position 10 + 30 = 40
after the second jump, at position 10 + 30 + 30 = 70
after the third jump, at position 10 + 30 + 30 + 30 = 100
Assume that: X, Y and D are integers within the range
[1..1,000,000,000]; X ≤ Y. Complexity: expected worst-case time
complexity is O(1); expected worst-case space complexity is O(1).
The question was pretty straight forward and it took me like 2 minutes to write the solution, which is following,
class Solution {
public int solution(int X, int Y, int D) {
int p = 0;
while (X < Y){
p++;
X = X + D;
}
return p;
}
}
However, the test result shows that the performance of my code is just 20% and I scored just 55%,
Here is the link to result, https://codility.com/demo/results/demo66WP2H-K25/
That was so simple code, where I have just used a single while loop, how could it possibly be make much faster ?
Basic math:
X + nD >= Y
nD >= Y - X
n >= (Y - X) / D
The minimum value for n will be the result of rounding up the division of (Y - X) by D.
Big O analysis for this operation:
Complexity: O(1). It's a difference, a division and a round up
Worst-case space complexity is O(1): you can have at most 3 more variables:
Difference for Y - X, let's assign this into Z.
Division between Z by D, let's assign this into E.
Rounding E up, let's assign this into R (from result).
Java(One Line), Correctness 100%, Performance 100%, Task score 100%
// you can also use imports, for example:
// import java.util.*;
// you can write to stdout for debugging purposes, e.g.
// System.out.println("this is a debug message");
class Solution {
public int solution(int X, int Y, int D) {
return (int) Math.ceil((double) (Y - X) / (double) D);
}
}
Here is the 100% total score Python solution:
def solution(X, Y, D):
# write your code in Python 3.6
s = (Y-X)/D
return int(-(-s // 1))
class Solution {
public int solution(int x, int y, int d) {
return (y - x + d - 1) / d;
}
}
class Solution {
public int solution(int x, int y, int d) {
// write your code in Java SE 8
System.out.println("this is a debug message"+(y-x)%d);
if((y-x)%d == 0)
return ((y-x)/d);
else
return (((y-x)/d)+1);
}
}
C# got 100 out of 100 points
using System;
// you can also use other imports, for example:
// using System.Collections.Generic;
// you can write to stdout for debugging purposes, e.g.
// Console.WriteLine("this is a debug message");
class Solution {
public int solution(int X, int Y, int D) {
int Len= Y-X;
if (Len%D==0)
{
return Len/D;
}
else
{
return (Len/D)+1;
}
}
}
Here's Scala solution:
def solution(X: Int, Y: Int, D: Int): Int = {
//divide distance (Y-X) with fixed jump distance. If there is reminder then add 1 to result to
// cover that part with one jump
val jumps = (Y-X) / D + (if(((Y-X) % D) >0 ) 1 else 0)
jumps
}
Performance: https://codility.com/demo/results/trainingTQS547-ZQW/
Javascript solution, 100/100, and shorter than the existing answer:
function solution(Y, Y, D) {
return Math.ceil((Y - X) / D);
}
Here is a solution that brings the test performance to 100%
class Solution {
public int solution(int X, int Y, int D) {
if (X >= Y) return 0;
if (D == 0) return -1;
int minJump = 0;
if ((Y - X) % D == 0) {
minJump = (Y - X) / D;
} else minJump= (Y - X) / D +1;
return minJump;
}
}
JavaScript solution 100/100
function solution (x,y,d) {
if ((y-x) % d === 0) {
return (y-x)/d;
} else {
return Math.ceil((y-x)/d);
}
}
Using Java perfect code
100 score code in Java
public int solution(int X, int Y, int D) {
if(X<0 && Y<0)
return 0;
if(X==Y)
return 0;
if((Y-X)%D==0)
return (Y-X)/D;
else
return (((Y-X)/D)+1);
}
this is corrected code using java giving 91% pass
int solution(int A[]) {
int len = A.length;
if (len == 2) {
return Math.abs(A[1] - A[0]);
}
int[] sumArray = new int[A.length];
int sum = 0;
for (int j = 0; j < A.length; j++) {
sum = sum + A[j];
sumArray[j] = sum;
}
int min = Integer.MAX_VALUE;
for (int j = 0; j < sumArray.length; j++) {
int difference = Math.abs(sum - 2 * sumArray[j]);
// System.out.println(difference);
if (difference < min)
min = difference;
}
return min;
}
This is my solution with 100% (C#):
int result = 0;
if (y <= x || d == 0)
{
result = 0;
}
else
{
result = (y - x + d - 1) / d;
}
return result;
Here is my solution in PHP, 100% performance.
function solution($X, $Y, $D) {
return (int)ceil(($Y-$X)/$D); //ceils returns a float and so we cast (int)
}
Y-X gives you the actual distance object has to be travel ,if that distance is directly divsible by object jump(D) then ans will be (sum/D) if some decimal value is there then we have to add 1 more into it i.e(sum/D)+1
int sum=Y-X;
if(X!=Y && X<Y){
if(sum%D==0){
return (int )(sum/D);
}
else{
return ((int)(sum/D)+1);
}}
else{
return 0;
}
I like all the rest of the solutions, especially "(y - x + d - 1) / d". That was awesome. This is what I came up with.
public int solution(int X, int Y, int D) {
if (X == Y || X > Y || D == 0) {
return 0;
}
int total = (Y - X) / D;
int left = (Y - X) - (D * total);
if (left > 0) {
total++;
}
return total;
}
// you can write to stdout for debugging purposes, e.g.
// console.log('this is a debug message');
function solution(X, Y, D) {
let jumps = 0
//If 0 -> 100 with 2 step
// Answer would be 100/2 = 50
//If 10 -> 100 with 2 step
//Answer would be (100 - 10) / 2 = 45
jumps = Math.ceil((Y - X) / D)
return jumps
}
swift solution 100% PASS - O(1) complexity
import Foundation
import Glibc
public func solution(_ X : Int, _ Y : Int, _ D : Int) -> Int {
if X == Y {
return 0
}
var jumps = (Y-X)/D
if jumps * D + X < Y {
jumps += 1
}
return jumps
}
import math
def solution(X, Y, D):
if (X >= Y): return 0
if (D == 0): return -1
minJump = 0
#if ((Y - X) % D == 0):
minJump = math.ceil((Y - X) / D)
#else:
#minJump = math.ceil((Y - X) / D) +1
return minJump
This solution worked for me in Java 11:
public int solution(int X, int Y, int D) {
return X == Y ? 0 : (Y - X - 1) / D + 1;
}
Correctness 100%, Performance 100%, Task score 100%
#Test
void solution() {
assertThat(task1.solution(0, 0, 30)).isEqualTo(0);
assertThat(task1.solution(10, 10, 10)).isEqualTo(0);
assertThat(task1.solution(10, 10, 30)).isEqualTo(0);
assertThat(task1.solution(10, 30, 30)).isEqualTo(1);
assertThat(task1.solution(10, 40, 30)).isEqualTo(1);
assertThat(task1.solution(10, 45, 30)).isEqualTo(2);
assertThat(task1.solution(10, 70, 30)).isEqualTo(2);
assertThat(task1.solution(10, 75, 30)).isEqualTo(3);
assertThat(task1.solution(10, 80, 30)).isEqualTo(3);
assertThat(task1.solution(10, 85, 30)).isEqualTo(3);
assertThat(task1.solution(10, 100, 30)).isEqualTo(3);
assertThat(task1.solution(10, 101, 30)).isEqualTo(4);
assertThat(task1.solution(10, 105, 30)).isEqualTo(4);
assertThat(task1.solution(10, 110, 30)).isEqualTo(4);
}
Here is the JS implementation
function frogJumbs(x, y, d) {
if ((y - x) % d == 0) {
return Math.floor((y - x) / d);
}
return Math.floor((y - x) / d + 1);
}
console.log(frogJumbs(0, 150, 30));
100% C# solution:
public int solution(int X, int Y, int D)
{
var result = Math.Ceiling((double)(Y - X) / D);
return Convert.ToInt32(result);
}
It divides the total distance by length of a jump and rounds up the result. It came after multiple attempts and some web searches.
Here is the solution in Python giving a score of 100 on Codility:
import math
return math.ceil((Y-X)/D)

Cut a polygon into 4 parts with equals area. java

I need to cut a convex not simple polygon by two perpendicular lines to divide it into 4 equal(area) parts.
I wrote a program, but it does not pass tests.
I think the reason is rounding errors or my function of calculating area.
Please check it, is it correct?
I use shoelace algorithm and heron's formula
Here is the code:
double calcArea() {
double result = 0;
if (size() > 4) {
int j = size() - 1;
for (int i = 0; i < size() - 1; i++) {
result += (points.get(i).getX() + points.get(j).getX())
*
(points.get(j).getY() - points.get(i).getY());
j = i;
}
result = result / (result >= 0 ? 2. : -2.);
} else if(size() == 3) {
double c,a,b, p;
c = Math.sqrt(Math.pow(points.get(0).getY()-points.get(1).getY(),2)+Math.pow(points.get(0).getX()-points.get(1).getX(),2));
a = Math.sqrt(Math.pow(points.get(1).getY()-points.get(2).getY(),2)+Math.pow(points.get(1).getX()-points.get(2).getX(),2));
b = Math.sqrt(Math.pow(points.get(0).getY()-points.get(2).getY(),2)+Math.pow(points.get(0).getX()-points.get(2).getX(),2));
p = (a + b + c) / 2.;
return Math.sqrt(p*(p-a)*(p-b)*(p-c));
}
return result;
}
What I do in:
finding of point(x, y) of cutting polygon.
I cut it by x = a in [ min(x), max(x)]
and calculate S'(part of polygon from x=min(x) to x=a)
if S' = S/2 , i take a for calculating value(a, *)
then the same with y = b whereb in [min(y), max(y)]
Is there more fast method?

Integer Factorization

Could anyone explain to me why the algorithm below is an error-free integer factorization method that always return a non-trivial factor of N.
I know how weird this sounds, but I designed this method 2 years ago and still don't understand the mathematical logic behind it, which is making it difficult for me to improve it. It's so simple that it involves only addition and subtraction.
public static long factorX( long N )
{
long x=0, y=0;
long b = (long)(Math.sqrt(N));
long a = b*(b+1)-N;
if( a==b ) return a;
while ( a!= 0 )
{
a-= ( 2+2*x++ - y);
if( a<0 ) { a+= (x+b+1); y++; }
}
return ( x+b+1 );
}
It seems that the above method actually finds a solution by iteration to the diophantine equation:
f(x,y) = a - x(x+1) + (x+b+1)y
where b = floor( sqrt(N) ) and a = b(b+1) - N
that is, when a = 0, f(x,y) = 0 and (x+b+1) is a factor of N.
Example: N = 8509
b = 92, a = 47
f(34,9) = 47 - 34(34+1) + 9(34+92+1) = 0
and so x+b+1 = 127 is a factor of N.
Rewriting the method:
public static long factorX(long N)
{
long x=1, y=0, f=1;
long b = (long)(Math.sqrt(N));
long a = b*(b+1)-N;
if( a==b ) return a;
while( f != 0 )
{
f = a - x*(x+1) + (x+b+1)*y;
if( f < 0 ) y++;
x++;
}
return x+b+1;
}
I'd really appreciate any suggestions on how to improve this method.
Here's a list of 10 18-digit random semiprimes:
349752871155505651 = 666524689 x 524741059 in 322 ms
259160452058194903 = 598230151 x 433211953 in 404 ms
339850094323758691 = 764567807 x 444499613 in 1037 ms
244246972999490723 = 606170657 x 402934339 in 560 ms
285622950750261931 = 576888113 x 495109787 in 174 ms
191975635567268981 = 463688299 x 414018719 in 101 ms
207216185150553571 = 628978741 x 329448631 in 1029 ms
224869951114090657 = 675730721 x 332780417 in 1165 ms
315886983148626037 = 590221057 x 535201141 in 110 ms
810807767237895131 = 957028363 x 847213937 in 226 ms
469066333624309021 = 863917189 x 542952889 in 914 ms
OK, I used Matlab to see what was going here. Here is the result for N=100000:
You are increasing x on each iteration, and the funny pattern of a variable is strongly related with the remainder N % x+b+1 (as you can see in the gray line of the plot, a + (N % (x+b+1)) - x = floor(sqrt(N))).
Thus, I think you are just finding the first factor larger than sqrt(N) by simple iteration, but with a rather obscure criterion to decide it is really a factor :D
(Sorry for the half-answer... I have to leave, I will maybe continue later).
Here is the matlab code, just in case you want it to test by yourself:
clear all
close all
N = int64(100000);
histx = [];
histDiffA = [];
histy = [];
hista = [];
histMod = [];
histb = [];
x=int64(0);
y=int64(0);
b = int64(floor(sqrt(double(N))));
a = int64(b*(b+1)-N);
if( a==b )
factor = a;
else
while ( a ~= 0 )
a = a - ( 2+2*x - y);
histDiffA(end+1) = ( 2+2*x - y);
x = x+1;
if( a<0 )
a = a + (x+b+1);
y = y+1;
end
hista(end+1) = a;
histb(end+1) = b;
histx(end+1) = x;
histy(end+1) = y;
histMod(end+1) = mod(N,(x+b+1));
end
factor = x+b+1;
end
figure('Name', 'Values');
hold on
plot(hista,'-or')
plot(hista+histMod-histx,'--*', 'Color', [0.7 0.7 0.7])
plot(histb,'-ob')
plot(histx,'-*g')
plot(histy,'-*y')
legend({'a', 'a+mod(N,x+b+1)-x', 'b', 'x', 'y'}); % 'Input',
hold off
fprintf( 'factor is %d \n', factor );
Your method is a variant of trial multiplication of (n-a)*(n+b), where n=floor(sqrt(N)) and b==1.
The algorithm then iterates a-- / b++ until the difference of the (n-a)*(n+b) - N == 0.
The partial differences (in respect of a and b) are in proportion to 2b and 2a respectively. Thus no true multiplication are necessary.
The complexity is a linear function of |a| or |b| -- the more "square" N is, the faster the method converges. In summary, there are much faster methods, one of the easiest to understand being the quadratic residue sieve.
Pardon my c#, I don't know Java.
Stepping x and y by 2 increases algorithm speed.
using System.Numerics; // needed for BigInteger
/* Methods ************************************************************/
private static BigInteger sfactor(BigInteger k) // factor odd integers
{
BigInteger x, y;
int flag;
x = y = iSqrt(k); // Integer Square Root
if (x % 2 == 0) { x -= 1; y += 1; } // if even make x & y odd
do
{
flag = BigInteger.Compare((x*y), k);
if (flag > 0) x -= 2;
y += 2;
} while(flag != 0);
return x; // return x
} // end of sfactor()
// Finds the integer square root of a positive number
private static BigInteger iSqrt(BigInteger num)
{
if (0 == num) { return 0; } // Avoid zero divide
BigInteger n = (num / 2) + 1; // Initial estimate, never low
BigInteger n1 = (n + (num / n)) >> 1; // right shift to divide by 2
while (n1 < n)
{
n = n1;
n1 = (n + (num / n)) >> 1; // right shift to divide by 2
}
return n;
} // end iSqrt()

How to re-implement sin() method in Java ? (to have results close to Math.sin() )

I know Math.sin() can work but I need to implement it myself using factorial(int) I have a factorial method already below are my sin method but I can't get the same result as Math.sin():
public static double factorial(double n) {
if (n <= 1) // base case
return 1;
else
return n * factorial(n - 1);
}
public static double sin(int n) {
double sum = 0.0;
for (int i = 1; i <= n; i++) {
if (i % 2 == 0) {
sum += Math.pow(1, i) / factorial(2 * i + 1);
} else {
sum += Math.pow(-1, i) / factorial(2 * i + 1);
}
}
return sum;
}
You should use the Taylor series. A great tutorial here
I can see that you've tried but your sin method is incorrect
public static sin(int n) {
// angle to radians
double rad = n*1./180.*Math.PI;
// the first element of the taylor series
double sum = rad;
// add them up until a certain precision (eg. 10)
for (int i = 1; i <= PRECISION; i++) {
if (i % 2 == 0)
sum += Math.pow(rad, 2*i+1) / factorial(2 * i + 1);
else
sum -= Math.pow(rad, 2*i+1) / factorial(2 * i + 1);
}
return sum;
}
A working example of calculating the sin function. Sorry I've jotted it down in C++, but hope you get the picture. It's not that different :)
Your formula is wrong and you are getting a rough result of sin(1) and all you're doing by changing n is changing the accuracy of this calculation. You should look the formula up in Wikipedia and there you'll see that your n is in the wrong place and shouldn't be used as the limit of the for loop but rather in the numerator of the fraction, in the Math.pow(...) method. Check out Taylor Series
It looks like you are trying to use the taylor series expansion for sin, but have not included the term for x. Therefore, your method will always attempt to approximate sin(1) regardless of argument.
The method parameter only controls accuracy. In a good implementation, a reasonable value for that parameter is auto-detected, preventing the caller from passing to low a value, which can result in highly inaccurate results for large x. Moreover, to assist fast convergence (and prevent unnecessary loss of significance) of the series, implementations usually use that sin(x + k * 2 * PI) = sin(x) to first move x into the range [-PI, PI].
Also, your method is not very efficient, due to the repeated evaluations of factorials. (To evaluate factorial(5) you compute factorial(3), which you have already computed in the previous iteration of the for-loop).
Finally, note that your factorial implementation accepts an argument of type double, but is only correct for integers, and your sin method should probably receive the angle as double.
Sin (x) can be represented as Taylor series:
Sin (x) = (x/1!) – (x3/3!) + (x5/5!) - (x7/7!) + …
So you can write your code like this:
public static double getSine(double x) {
double result = 0;
for (int i = 0, j = 1, k = 1; i < 100; i++, j = j + 2, k = k * -1) {
result = result + ((Math.pow(x, j) / factorial (j)) * k);
}
return result;
}
Here we have run our loop only 100 times. If you want to run more than that you need to change your base equation (otherwise infinity value will occur).
I have learned a very good trick from the book “How to solve it by computer” by R.G.Dromey. He explain it like this way:
(x3/3! ) = (x X x X x)/(3 X 2 X 1) = (x2/(3 X 2)) X (x1/1!) i = 3
(x5/5! ) = (x X x X x X x X x)/(5 X 4 X 3 X 2 X 1) = (x2/(5 X 4)) X (x3/3!) i = 5
(x7/7! ) = (x X x X x X x X x X x X x)/(7 X 6 X 5 X 4 X 3 X 2 X 1) = (x2/(7 X 6)) X (x5/5!) i = 7
So the terms (x2/(3 X 2)) , (x2/(5 X 4)), (x2/(7 X 6)) can be expressed as x2/(i X (i - 1)) for i = 3,5,7,…
Therefore to generate consecutive terms of the sine series we can write:
current ith term = (x2 / ( i X (i - 1)) ) X (previous term)
The code is following:
public static double getSine(double x) {
double result = 0;
double term = x;
result = x;
for (int i = 3, j = -1; i < 100000000; i = i + 2, j = j * -1) {
term = x * x * term / (i * (i - 1));
result = result + term * j;
}
return result;
}
Note that j variable used to alternate the sign of the term .

Categories