Leibnitz Method for Pi Program - java

I am making a program to prove Leibnitz method for computing PI.
(pi/4) = 1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 + ...
I took a very interesting approach to this and I am just wondering if there is a much easier way to do this.
What I did was I made the variable j the denominator. and the main idea was to have a counter start at -3 then go to Absolute value of -5 then -7 then absolute values of -9...so on. Do you think there is any way to make it smaller? Thanks :)
(To end the loop the teacher said to find the absolute difference and have that be < 1e-6)
public class Leibnitz
{
public static void main(String argv[])
{
double answer = (Math.PI) / 4; //answer
double numTheory = 1; //answer
double j = -3; //counts the Denominator
double piFrac; //extra variable for calc
int i = 0; //counts loop
System.out.print("How many iterations does it take to compute pi this series: ");
while (Math.abs(answer - numTheory) > 1e-6)
{
if (j % 4 == -1) //checks if number should be negative (5,9,... needs to be positive so -5 % 4 = -1, -9 % 4 = -1)
j = Math.abs(j);
piFrac = (1 / j); //fraction of pie
numTheory = numTheory + piFrac; //answer
if (j > 0) //makes counter a negative
j = -j;
j -= 2; //goes down by 2
i++; //counts how many times it goes thru the loop
}
System.out.println(i);
}
}

If you are just looking for optimizations. This should work, it's much shorter and not too much less readable.
while (Math.abs(answer + numTheory) > 1e-6)
{
j += 2;
numTheory += 1 / (++i % 2 == 0 ? -j : j);
}
Explanation, the code (++i % 2 == 0 ? -j : j) gets evaluated as follows
(expression) ? (if branch) : (else branch)
so in english. if (++i mod 2 equals 0) then do (-j) else do (j)
Full code:
public class Leibnitz
{
public static void main(String argv[])
{
double answer = Math.PI / 4; //answer
double numTheory = 1; //answer
double j = -3; //counts the Denominator
int i = 0; //counts loop
System.out.print("How many iterations does it take to compute pi this series: ");
while (Math.abs(answer + numTheory) > 1e-6)
{
j += 2;
numTheory += 1 / (++i % 2 == 0 ? -j : j);
}
System.out.println(i);
}
}

Related

Represent an Integer as a sum of Consecutive positive integers

I am writing code for counting the number of ways an integer can be represented as a sum of the consecutive integers. For Example
15=(7+8),(1+2+3+4+5),(4+5+6). So the number of ways equals 3 for 15.
Now the input size can be <=10^12. My program is working fine till 10^7(i think so, but not sure as i didnt check it on any online judge. Feel free to check the code for that)
but as soon as the i give it 10^8 or higher integer as input. it throws many runtime exceptions(it doesnt show what runtime error). Thanks in advance.
import java.io.*;
//sum needs to contain atleast 2 elements
public class IntegerRepresentedAsSumOfConsecutivePositiveIntegers
{
public static long count = 0;
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
long num = Long.parseLong(br.readLine()); //Enter a number( <=10^12)
driver(num);
System.out.println("count = " + count);
}
public static void driver(long num)
{
long limit = num / 2;
for(long i = 1 ; i <= limit ; i++)
{
func(i,num);
}
}
public static void func(long i,long num)
{
if(i < num)
{
func(i + 1,num - i);
}
else if(i > num)
{
return;
}
else
{
count++;
}
}
}
Use some math: if arithmetic progression with difference 1 starts with a0 and contains n items, then its sum is
S = (2 * a0 + (n-1))/2 * n = a0 * n + n * (n-1) / 2
note that the second summand rises as quadratic function. So instead of checking all a0 in range S/2, we can check all n is smaller range
nmax = Ceil((-1 + Sqrt(1 + 8 * S)) / 2)
(I used some higher approximation).
Just test whether next expression gives integer positive result
a0 = (S - n * (n - 1) / 2) / n
Recursive function isn't suitable when you have big input size like your case.
The maximum depth of the java call stack is about 8900 calls and sometimes only after 7700 calls stack overflow occurs so it really depends on your program input size.
Try this algorithm I think it worked for your problem:
it will work fine until 10^9 after that it will take much more time to finish running the program.
long sum = 0;
int count = 0;
long size;
Scanner in = new Scanner(System.in);
System.out.print("Enter a number <=10^12: ");
long n = in.nextLong();
if(n % 2 != 0){
size = n / 2 + 1;
}
else{
size = n / 2;
}
for(int i = 1; i <= size; i++){
for(int j = i; j <= size; j++){
sum = sum + j;
if(sum == n){
sum = 0;
count++;
break;
}
else if(sum > n){
sum = 0;
break;
}
}
}
System.out.println(count);
Output:
Enter a number <=10^12: 15
3
Enter a number <=10^12: 1000000000
9
BUILD SUCCESSFUL (total time: 10 seconds)
There's a really excellent proof that the answer can be determined by solving for the unique odd factors (Reference). Essentially, for every odd factor of a target value, there exists either an odd series of numbers of that factor multiplied by its average to produce the target value, or an odd average equal to that factor that can be multiplied by double an even-sized series to reach the target value.
public static int countUniqueOddFactors(long n) {
if (n==1) return 1;
Map<Long, Integer> countFactors=new HashMap<>();
while ((n&1)==0) n>>>=1; // Eliminate even factors
long divisor=3;
long max=(long) Math.sqrt(n);
while (divisor <= max) {
if (n % divisor==0) {
if (countFactors.containsKey(divisor)) {
countFactors.put(divisor, countFactors.get(divisor)+1);
} else {
countFactors.put(divisor, 1);
}
n /= divisor;
} else {
divisor+=2;
}
}
int factors=1;
for (Integer factorCt : countFactors.values()) {
factors*=(factorCt+1);
}
return factors;
}
As #MBo noted, if a number S can be partitioned into n consecutive parts, then S - T(n) must be divisible by n, where T(n) is the n'th triangular number, and so you can count the number of partitions in O(sqrt(S)) time.
// number of integer partitions into (at least 2) consecutive parts
static int numberOfTrapezoidalPartitions(final long sum) {
assert sum > 0: sum;
int n = 2;
int numberOfPartitions = 0;
long triangularNumber = n * (n + 1) / 2;
while (sum - triangularNumber >= 0) {
long difference = sum - triangularNumber;
if (difference == 0 || difference % n == 0)
numberOfPartitions++;
n++;
triangularNumber += n;
}
return numberOfPartitions;
}
A bit more math yields an even simpler way. Wikipedia says:
The politeness of a positive number is defined as the number of ways it can be expressed as the sum of consecutive integers. For every x, the politeness of x equals the number of odd divisors of x that are greater than one.
Also see: OEIS A069283
So a simple solution with lots of room for optimization is:
// number of odd divisors greater than one
static int politeness(long x) {
assert x > 0: x;
int p = 0;
for (int d = 3; d <= x; d += 2)
if (x % d == 0)
p++;
return p;
}

Questions about moduls and return statement

I have two questions about this of code.
Can someone explain me, what the if statement is doing exactly. I know that count has to increment every time the test is true, but I'm not sure what the this n % i == 0 is doing.
My second question is, how can I print the return statement's answer on the console?
int n = 10;
countFactors(n);
}
public static int countFactors(int n){
int count = 0;
for (int i = 1; i <= n; i++){
if (n % i == 0) //this line
count++;
}
return count;
}
}
It count the number of divisor in your range 1-n so for example :
if n = 10 the result will be 4 because there are 4 divisor:
1
2
5
10
and about how you print in console :
for (int i = 1; i <= n; i++) {
if (n % i == 0) {
count++;
System.out.println(i);
}
}
System.out.println("Number or disivor = " + count);
You can learn here : Table of divisors
Well, as the name of the method suggests, the count represents the number of divisors that n has.
The if statement tests the following: Is n divisible by i?. in other words: Is n/i a whole number?
if you were to use:
if(n%i == 1)
instead, then it would count the numbers for which: n/i has a remainder of 1.
in order to print the return statement, you can add this line just before the return:
public static int countFactors(int n){
int count = 0;
for (int i = 1; i <= n; i++){
if (n % i == 0)
count++;
}
System.out.println(count);//adding this
return count;
}
The % operator (known as the remainder or Modulus operator) basically divides a number by another and gives you the remainder and nothing else. For instance, if you do 4 % 2, it would give you 0 because 2 goes into 4 evenly. If you would do 4 % 3 it would give you 1 because that's the remainder of 4 / 3. Also look at this website: http://www.cafeaulait.org/course/week2/15.html
The countFactors method loops 1 to n and includes n. If you do 10 % 1, you would get 0 because one goes into 10 evenly so the count would be incremented.

finding the sum of the sreies, using java

the question is to find the sum of this series
series
i used this code to solve it , but im not quite sure the logic is correct.
the noofterms is how many terms are going to be added
and x is the number that will be assigned to the variable.
does the logic seem correct?
public static double sumOfSeries(double x, int noofterms){
double evennumbers=1;
double oddnumbers=1;
double result=1;
// since the power of x starts from 1 , we start i from 1 and increment by 2
for (int i=1; i<noofterms; i+=2 ){
// we reset starting numbers so we start from them everytime
evennumbers = 1;
oddnumbers = 1;
// everytime the number increases by 2 when it is smaller than i+1
// ex when its equal to 2 , j = 3 , j+1 = 4 so it increments by 2
// when its 4 , j = 5 , j+ 1 = 6 , it increments
for (int j=2; j<=i+1; j+=2){
// multiply by increments of 2
evennumbers= evennumbers * j;
}
// it starts from 1 and increments by 2 so it goes like 1,3,5
for (int z=1; z<=i; z+=2){
oddnumbers = oddnumbers * z;
}
result*=((Math.pow(x, (double)i)) / (double)i) + (oddnumbers/evennumbers);
}
return result;
}
You can do it better. Note that numerators and denominators form two sequences, so you can keep previous terms to efficiently make computations, this will look like this :
long even = 1;
long odd = 1;
double result = x;
for(long i = 1; i < noofterms; i++)
{
even *= 2 * i;
odd *= 2 * i - 1;
double oper = Math.pow(x, (double)(2 * i + 1)) / (double)(2 * i + 1);
result += (double)even / (double)odd * oper;
}
You can improve by using logarithms because even and odd will grow very fast and will lead to overflows :
double even = 0.0;
double odd = 0.0;
double result = x;
double logx = Math.log(x);
for(long i = 1; i < noofterms; i++)
{
even += Math.log((double)(2 * i));
odd += Math.log((double)(2 * i - 1));
double oper = logx * (2 * i + 1) - Math.log((double)(2 * i + 1));
result += Math.exp(even - odd + oper);
}
EDIT: only one sequence could also be computed : p *= (double)(2*i)/(2*i-1). Then the log trick is not useful.

I have some questions regarding this tracing

public class Task {
public static void main(String args[]) {
int x = 0, p = 0, sum = 0;
p = 1;
x = 2;
double q;
sum = 0;
while (p < 12) {
q = x + p - (sum + 5 / 3) / 3.0 % 2;
sum = sum + (x++) + (int) q;
System.out.println(sum);
if (x > 5)
p += 4 / 2;
else
p += 3 % 1;
}
sum = sum + p;
System.out.println(sum);
}
}
While proceeding to line 12 (sum = sum + (x++) + (int)q;) i thought sum should be 5 but actually the output is 4. I tried line 12 in the interactions pane and indeed saw that sum=4. I don't get it. Shouldn't x++ yield 3 (x=2) and if this gets added to (int) q ( double q gave me sth like 2.666666), i should be getting 5. Can someone explain to me what happened?
Additionally,after getting my first output, how should I proceed?
The next condition is:
if (x > 5)
p += 4 / 2;
else
p += 3 % 1;
since x<5, i should go for the else condition, right?
My last question is that, after using p += 3%1, my p still remains 1, so do i return back to this loop (since p<12) or do I get out of this loop and proceed to line19? I'm not sure what to do.
In line 12 you are using post increment (x++). You should use pre increment ++x.
Post increment puts the current value of x in your statement, then increases x.
Pre increment initially increases x and after that puts result into your statement.
At your first time, 3%1=0
p +=3%1 => p+=0 thats why p still remains 1

Method using recursion causing code to fail at run time, involves global variable

This question is poorly worded, but how do I make my code run as desired without getting about a hundred error messages at run time when I use recursion? This is my faulty program
public class Collatz
{
public static int count;
public static int pluscount() {
return count++;
}
public static void collatz (int n)
{
if (n < count) {
System.out.print(n + "");
}
if (n == 1) return;
if (n % 2 == 0) {
pluscount();
collatz(n / 2);
}
else {
pluscount();
collatz(3*n + 1);
}
}
public static void main(String[] args)
{
int N = Integer.parseInt(args[0]);
int[] array = new int [N+1];
for (int i = 0; i <= N; i++) {
count = 0;
collatz(i);
array [i] = count;
}
int max = StdStats.max(array);
System.out.println(max);
}
}
If I change the collatz() method to
public static void collatz (int n)
{
count ++;
StdOut.print(n + "");
if (n == 1 || n == 0) return;
if (n % 2 == 0) collatz(n / 2);
else
collatz(3*n + 1);
}
and remove the pluscount() from my code, and input 7 as the argument, the code runs and prints 01213105168421421516842163105168421722113417522613402010516842117
175226134020105168421, but it's supposed to print 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
Here are the instructions from my Java textbook if anyone doesn't understand what I'm trying to accomplish:
Consider the following recursive function, which is related to a famous unsolved problem in number theory, known as the Collatz problem or the 3n + 1 problem.
public static void collatz(int n) {
System.out.print(n + " ");
if (n == 1) return;
if (n % 2 == 0) collatz(n / 2);
else collatz(3*n + 1);
}
For example, a call to collatz(7) prints the sequence
7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
as a consequence of 17 recursive calls. Write a program that takes a command-line argument N and returns the value of n < N for which the number of recursive calls for collatz(n) is maximized.
There are two problem with your code
1.For loop in main method starts with 0 which causes problem.Start iterating from 1
for (int i = 1; i <= N; i++)
2.No need to put if (n < count) in collatz method
When you call collatz(i) and get the result, I would not save it to an array. Instead just keep track of you max count and your max n. Something like this should do the trick based on the approach you are going:
public static int count;
public static void collatz(int n) {
count++;
//System.out.print(n + " ");
if (n == 1) return;
if (n % 2 == 0) collatz(n / 2);
else collatz(3*n + 1);
}
public static void main(String[] args)
{
int N = Integer.parseInt(args[0]);
int maxn = 0;
int maxCount = 0;
for (int i=1; i<=N; i++){ //Start at 1 since collatz(0) is infinite
count = 0;
collatz(i);
if (count>maxCount){
maxCount = count;
maxn = i;
}
}
System.out.println("your max n is: "+maxn);
}
Also notice that I commented out the print statment in collatz. The problem just focuses on how many recursion calls are being made. We do not really care what the output is during all of the recursion calls.
Hope this helps.

Categories

Resources