What is wrong with my pi calculator? - java

I'm using Wallis' method to calculate pi, and I think I did it right. At least I thought I did anyway. I think the problem (output is 0)has to do with rounding and remainders, though I can't be sure. Here's the code:
import java.util.Scanner;
public class WallisPi {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int a = 2;
int b = 3;
int c = 1;
int pi = 0;
double acc = 0.0;
int n = scan.nextInt();
scan.close();
for (int i = 0; i <= n; i++) {
pi = (2 / 3) * c;
if (a > b) {
b += 2;
} else {
a += 2;
}
c = a / b;
}
pi *= 4;
System.out.println("The approximation of pi is " + pi + ".");
acc = Math.PI - pi;
System.out.println("It is " + acc + " off.");
}
}
Since posting this I've made some changes to the code, though it's still not quite functional. I get 2.666..., so there's something else at work here as well.
import java.util.Scanner;
public class WallisPi {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
double a = 2.0;
double b = 3.0;
double c = 1.0;
double pi = 0;
double acc = 0.0;
int n = scan.nextInt();
scan.close();
for (int i = 0; i <= n; i++) {
pi = (2.0 / 3.0) * c;
if (a > b) {
b += 2;
} else {
a += 2;
}
c = a / b;
}
pi *= 4;
System.out.println("The approximation of pi is " + pi + ".");
acc = Math.PI - pi;
System.out.println("It is " + acc + " off.");
}
}

int a=2;
int b=3;
double pi=2;
for(int i=0;i<=n;i++){
pi *= (double)a/(double)b;
if(a>b){
b+=2;
} else {
a+=2;
}
}
pi*=2;
Using n = 4000 yields 3.141200
Here's the whole program, fixed:
import java.util.Scanner;
public class WallisPi {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
scan.close();
double pi = 2;
int a = 2;
int b = 3;
for (int i = 0; i <= n; i++){
pi *= (double) a / (double) b;
if (a > b) {
b += 2;
} else {
a += 2;
}
}
pi *= 2;
double acc = Math.PI - pi;
System.out.println("The approximation of pi is " + pi + ".");
System.out.println("It is " + acc + " off.");
}
}

Since your varibles are ints, all your divisions are integer divisions, omitting the fraction (and preserving only the whole part of the result). For accurate results, you should define your variables as doubles:
double a=2;
double b=3;
double c=1;
double pi=0;

Related

Using two methods in a class (Rational) to simplify a fraction

I have a class definition for a class of rational numbers. My assignment is to be able to add, multiply and divide any fraction I put in my main function. My program can do all that, but I'm having trouble simplifying the fractions. I want to try and use only two methods to simplify, for example public void reduce(); and private static gcd();
public class Rational {
private int num;
private int denom;
public Rational() {
num = 0;
denom = 1;
}
public Rational(int n, int d) {
num = n;
denom = d;
reduce();
}
public Rational plus(Rational t) {
int tnum = 0;
int tdenom = 1;
tnum = (this.num * t.denom) + (this.denom * t.num);
tdenom = (t.denom * this.denom);
Rational r = new Rational (tnum, tdenom);
return r;
}
public Rational minus(Rational t) {
int tnum = 0;
int tdenom = 1;
tnum = (this.num * t.denom) - (this.denom * t.num);
tdenom = (t.denom * this.denom);
Rational r = new Rational (tnum, tdenom);
return r;
}
public Rational multiply(Rational t) {
int tnum = 0;
int tdenom = 1;
tnum = this.num * t.num;
tdenom = t.denom * this.denom;
Rational r = new Rational (tnum, tdenom);
return r;
}
public Rational divide(Rational t) {
int tnum = 0;
int tdenom = 1;
tnum = this.num / t.num;
tdenom = this.denom / t.denom;
Rational r = new Rational (tnum, tdenom);
return r;
}
private static int gcd(int n, int d) {
return gcd(d, n%d);
}
public void reduce() {
//call gcd
gcd(num, denom);
//divide num and denom by gcd by
num = num / gcd(num,denom);
denom = denom / gcd(num,denom);
}
public String toString() {
return String.format("%d/%d", num, denom);
}
}
public class RationalMain {
public static void main(String[] args) {
Rational x = new Rational();
Rational y = new Rational(1,4);
Rational z = new Rational(1,2);
//x = y - z;
x = y.plus(z);
System.out.printf("%s = %s + %s\n", x.toString(), y.toString(), z.toString());
x = z.minus(y);
System.out.printf("%s = %s - %s\n", x.toString(), z.toString(), y.toString());
x = z.multiply(y);
System.out.printf("%s = %s * %s\n", x.toString(), z.toString(), y.toString());
x = y.divide(z);
System.out.printf("%s = %s / %s\n", x.toString(), y.toString(), z.toString());
}
}
That's not how you might achieve the Greatest Common Divisor (GCD). Before you will be able to get your code to work properly you will need to at least fix your gcd() method since currently it will recurse until an ArithmeticException (/ by zero) is generated. You might achieve the task this way:
private static int gcd(int num, int den) {
num = Math.abs(num); // if numerator is signed convert to unsigned.
int gcd = Math.abs(den); // if denominator is signed convert to unsigned.
int temp = num % gcd;
while (temp > 0) {
num = gcd;
gcd = temp;
temp = num % gcd;
}
return gcd;
}
To convert your fractions too their Lowest Terms your reduce() method might look like this if it accepted a Fraction String as an argument (you modify the method parameters if you like):
/*
A Fraction String can be supplied as: "1/2", or "2 1/2", or
"2-1/2, or "-2 32/64", or "-2-32/64". The last 2 examples are
negative fraction values.
*/
private String reduce(String fractionString) {
// Fraction can be supplied as: "1/2", or "2 1/2", or "2-1/2".
// Make sure it's a Fraction String that was supplied as argument...
inputString = inputString.replaceAll("\\s+", " ").trim();
if (!inputString.matches("\\d+\\/\\d+|\\d+\\s+\\d+\\/\\d+|\\d+\\-\\d+\\/\\d+")) {
return null;
}
str2 = new StringBuilder();
String wholeNumber, actualFraction;
if (inputString.contains(" ")) {
wholeNumber = inputString.substring(0, inputString.indexOf(" "));
actualFraction = inputString.substring(inputString.indexOf(" ") + 1);
str2.append(wholeNumber);
str2.append(" ");
}
else if (inputString.contains("-")) {
wholeNumber = inputString.substring(0, inputString.indexOf("-"));
actualFraction = inputString.substring(inputString.indexOf("-") + 1);
str2.append(wholeNumber);
str2.append("-");
}
else {
actualFraction = inputString;
}
String[] tfltParts = actualFraction.split("\\/");
int tfltNumerator = Integer.parseInt(tfltParts[0]);
int tfltDenominator = Integer.parseInt(tfltParts[1]);
// find the larger of the numerator and denominator
int tfltN = tfltNumerator;
int tfltD = tfltDenominator;
int tfltLargest;
if (tfltNumerator < 0) {
tfltN = -tfltNumerator;
}
if (tfltN > tfltD) {
tfltLargest = tfltN;
}
else {
tfltLargest = tfltD;
}
// Find the largest number that divides the numerator and
// denominator evenly
int tfltGCD = 0;
for (int tlftI = tfltLargest; tlftI >= 2; tlftI--) {
if (tfltNumerator % tlftI == 0 && tfltDenominator % tlftI == 0) {
tfltGCD = tlftI;
break;
}
}
// Divide the largest common denominator out of numerator, denominator
if (tfltGCD != 0) {
tfltNumerator /= tfltGCD;
tfltDenominator /= tfltGCD;
}
str2.append(String.valueOf(tfltNumerator)).append("/").append(String.valueOf(tfltDenominator));
return str2.toString();
}
As you can see, a whole number can also be supplied with your fraction so, if you do a call to the above reduce() method like this:
System.out.println(reduce("12-32/64"));
System.out.println(reduce("12 32/64"));
The console window will display:
12-1/2
12 1/2

BigInteger Java How To Recreate A Formula

I tried to recreate this formula i am sure it's correct but the problem it gives me infinity and i need your help to transform it to BigInteger please help if possible
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner Input = new Scanner(System.in);
double X = Input.nextDouble();
double Y = Input.nextDouble();
double Ans = 0;
for (int I = 1; I <= 20; I++) {
for (int J = 1; J <= 20; J++) {
Ans += Math.log10(1 + Math.exp(Math.pow(-1, I + J) * (((Math.pow(I, 2) * X)) + (Math.pow(J, 2)) * Y)));
}
}
System.out.println(Ans);
}
}

Having problems with negative signed numbers

I'm making a simple test in java, (i'm a begineer) and i was trying to make a program that calculates the discriminate of a second degree equation and displays the results, but when i change the sign of nom1 and nom2, the program doesn't displays any result, i've made some tests and i'm sure that the problem is there but i don't know how to resolve it.
Any help is welcome.
Here is my code:
public class test {
public static void main(String[] args) {
double a = 2;
double b = 5;
double c = 3;
double delta = b*b - 4 * a * c;
double den = 2 * a;
if(delta == 0){
double nom = b;
double pgcd = pgcd(nom, den);
double x0nom = nom/pgcd;
double x0den = den/pgcd;
System.out.println("x0 = "+String.valueOf(x0nom)+" / "+String.valueOf(x0den));
}else if(delta > 0){
// x1:
double nom1 = -b + Math.sqrt(delta);
double pgcd1 = pgcd(nom1, den);
int x1nom = (int) (nom1 / pgcd1);
int x1den = (int) (den / pgcd1);
// x2:
double nom2 = -b - Math.sqrt(delta);
double pgcd2 = pgcd(nom2, den);
int x2nom = (int) (nom2 / pgcd2);
int x2den = (int) (den / pgcd2);
System.out.println("pgcd = "+String.valueOf(pgcd1)+" "+String.valueOf(pgcd2));
System.out.println("x1 = "+String.valueOf(x1nom)+" / "+String.valueOf(x1den));
System.out.println("x2 = "+String.valueOf(x2nom)+" / "+String.valueOf(x2den));
}else if(delta < 0){
}
}
public static double pgcd(double a, double b) {
while (a != b) {
if (a < b){
b = b - a;
}else{
a = a - b;
}
}
return a;
}
}
Use BigInteger's gcd method
public static double pgcd(double a, double b) {
return (BigInteger.valueOf((long) a).gcd(BigInteger.valueOf((long) b)).intValue());
}

Pi with Nilakantha method

I am trying to calculate pi with the Nilakantha method. Whenever I run this program I get -Infinity if I input 1 and anything else I get NaN.
I am trying to modify my program that uses the Leibniz method, and I'm very new to java.
I appreciate all help!
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the number of calculations you would like to do");
long no = Long.parseLong(reader.readLine());
long cycle = 0;
long w = 2;
long x = 3;
long y = 4;
long z = 4;
long odd=1;
long i=1;
long a = 1;
long b = 1;
double pi= 0.0;
for(;i<=no;i++)
{
a = w*x*y;
b = x*y*z;
double currentTerm=0.0;
if (i%2==0)
{
currentTerm=(double)4/a;
cycle = cycle+1;
w = w+1;
x = x+1;
y = y+1;
}
else
{
currentTerm=(double)-4/b;
cycle = cycle+1;
x = x+1;
y = y+1;
z = z+1;
}
odd=odd+2;
pi = pi+currentTerm;
}
System.out.println("You calculated that pi is");
System.out.println(pi);
System.out.println(3.1415926535897932);
System.out.println("Pi is actually");
double error = pi/3.1415926535897932;
if(error >= 1) {
double bigerror=2-error;
System.out.println("Your accuracy is");
System.out.println(bigerror*100);
System.out.println("percent");
System.out.println(cycle);
}
else {
System.out.println("Your accuracy is");
System.out.println(error*100);
System.out.println("percent");
System.out.println(cycle);
}
}
}
On your first iteration a and b are both zeros.
I don't think you have your initialization part correct.
http://helloacm.com/two-simple-equations-to-compute-pi/
Here I see that j starts from 2.
You have zeroes.
Make sure you implement the algorithm correctly.
Here is your code corrected.
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class MainProgram {
public static void main(String[] args) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the number of calculations you would like to do");
long no = Long.parseLong(reader.readLine());
long step = 0;
double ans = 3;
long j = 2;
double pi = 0.0;
while (true) {
step++;
if ((step % 2) == 1) {
ans += 4.0 / (1.0 * j * (j + 1) * (j + 2));
} else {
ans -= 4.0 / (1.0 * j * (j + 1) * (j + 2));
}
j += 2;
pi = ans;
if (step >= no)
break;
}
System.out.println("You calculated that pi is");
System.out.println(pi);
System.out.println("Pi is actually");
System.out.println(3.1415926535897932);
double error = pi / 3.1415926535897932;
if (error >= 1) {
double bigerror = 2 - error;
System.out.print("Your accuracy is: ");
System.out.print(bigerror * 100);
System.out.println(" percent");
System.out.println(step);
} else {
System.out.print("Your accuracy is: ");
System.out.print(error * 100);
System.out.println(" percent.");
System.out.println(step);
}
}
}

Decimal Format Issue Java

I wrote a program and I can't figure out how i should do the decimal format? I thought i was doing it right, apparently i can't do decimal format correctly. Can, someone help me with the decimal format?
Here is my code:
import java.text.DecimalFormat;
import java.util.*;
public class Mean {
public static void main(String [] args){
Scanner s = new Scanner(System.in);
double[]x = new double[10];
int i;
for(i = 0;i < 10; i++){
x[i] = s.nextDouble();
}
double mean = mean(x, i);
double deviation = var(x);
System.out.println("The mean is " + mean);
System.out.println("The standard deviation is " + deviation);
}
public static double sum(double[] a) {
double sum = 0.0;
for (int i = 0; i < a.length; i++) {
sum += a[i];
}
return sum;
}
public static double mean(double[]x, double i){
if (x.length == 0) return Double.NaN;
double sum = sum(x);
return sum / x.length;
}
public static double var(double[] x) {
if (x.length == 0) return Double.NaN;
double avg = mean(x, 10);
double sum = 0.0;
for (int i = 0; i < x.length; i++) {
sum += (x[i] - avg) * (x[i] - avg);
}
DecimalFormat myFormatter = new DecimalFormat("#,##0.00");
return sum / myFormatter.format(Math.sqrt(x.length - 1));
}
}
Try this to format your double(s)... I also had to update you method var -
public static String formatDouble(double in) {
DecimalFormat myFormatter = new DecimalFormat(
"#,##0.00");
return myFormatter.format(in);
}
public static double var(double[] x) {
if (x.length == 0)
return Double.NaN;
double avg = mean(x);
double sum = 0.0;
for (int i = 0; i < x.length; i++) {
sum += (x[i] - avg) * (x[i] - avg);
}
return sum / Math.sqrt(x.length - 1);
}
public static void main(String[] args) {
double[] x = new double[] {
2000.20, 1000.10, 3000.30, 4000.40,5000.50,
6000.60,7000,70,8000.80,9000.90
};
double mean = mean(x);
double deviation = var(x);
System.out.println("The mean is "
+ formatDouble(mean));
System.out.println("The standard deviation is "
+ formatDouble(deviation));
}
The problem is the formatter return a String. you should return a String in the metod signature
public static String var(double[] x)
Also this line
return sum / myFormatter.format(Math.sqrt(x.length - 1));
Will not work if you are to return a String. You should do the calculations first, and then format it. Then return the formatted number
Edit: Try this, see if it works
public static String var(double[] x) {
if (x.length == 0)
return null;
double avg = mean(x, 10);
double sum = 0.0;
for (int i = 0; i < x.length; i++) {
sum += (x[i] - avg) * (x[i] - avg);
}
DecimalFormat myFormatter = new DecimalFormat("#,##0.00");
double result = sum / Math.sqrt(x.length - 1);
return myFormatter.format(result);
}
Then where you have this double deviation = var(x); replace it with String deviation = var(x);
Edit 2: complete code
import java.text.DecimalFormat;
import java.util.*;
public class Mean {
public static void main(String [] args){
Scanner s = new Scanner(System.in);
double[]x = new double[10];
int i;
for(i = 0;i < 10; i++){
x[i] = s.nextDouble();
}
double mean = mean(x, i);
String deviation = var(x); // changed to String
System.out.println("The mean is " + mean);
System.out.println("The standard deviation is " + deviation);
}
public static double sum(double[] a) {
double sum = 0.0;
for (int i = 0; i < a.length; i++) {
sum += a[i];
}
return sum;
}
public static double mean(double[]x, double i){
if (x.length == 0) return Double.NaN;
double sum = sum(x);
return sum / x.length;
}
public static String var(double[] x) { // changed return
if (x.length == 0)
return null;
double avg = mean(x, 10);
double sum = 0.0;
for (int i = 0; i < x.length; i++) {
sum += (x[i] - avg) * (x[i] - avg);
}
DecimalFormat myFormatter = new DecimalFormat("#,##0.00");
double result = sum / Math.sqrt(x.length - 1);
return myFormatter.format(result);
}
}
Update: correct standard deviation formula
double result = Math.sqrt(sum / (x.length - 1));
^^
You need to format the double at the time of print.If you tried at var() function and then assign with double deviation then it will give numberformatException due to special character that returns by Var().You can run this code It will give you the output.
public static void main(String[] args) throws ParseException {
Scanner s = new Scanner(System.in);
double[]x = new double[10];
int i;
for(i = 0;i < 2; i++){
x[i] = s.nextDouble();
}
double mean = mean(x, i);
double deviation = var(x);
DecimalFormat myFormatter = new DecimalFormat("#,##0.00");
System.out.println("The mean is " + mean);
System.out.println("The standard deviation is " +myFormatter.format(deviation));
}
public static double sum(double[] a) {
double sum = 0.0;
for (int i = 0; i < a.length; i++) {
sum += a[i];
}
return sum;
}
public static double mean(double[]x, double i){
if (x.length == 0) return Double.NaN;
double sum = sum(x);
return sum / x.length;
}
public static double var(double[] x) {
if (x.length == 0) return Double.NaN;
double avg = mean(x, 10);
double sum = 0.0;
for (int i = 0; i < x.length; i++) {
sum += (x[i] - avg) * (x[i] - avg);
}
return sum / Math.sqrt(x.length - 1);
}

Categories