Leibniz Formula using Java - java

The Leibniz formula for pi is: pi/4 = 1 - 1/3 + 1/5 - 1/7 + 1/9... I am trying to write this in Java but am running into a problem where the output is always 4 (which is not the value of pi). I put my code in a java visualizer and it seems that the problem is that when the code falls into the else statement, it is not subtracting (1-denominator) from pi and that is making the prevPi value and the pi value the same which is causing the do/while loop to end. Does anyone know how I can fix this?
My code:
public static float piCalculatorLeibniz() {
float pi = 0;
int denominator = 1;
float prevPi = 0;
boolean keepGoing = true;
int i = 0;
while (keepGoing == true) {
prevPi = pi;
if (i % 2 == 0) {
pi += (1/denominator);
} else {
pi -= (1/denominator);
}
i++;
denominator += 2;
if (pi == prevPi) {
keepGoing = false;
}
}
pi *= 4;
return pi;
}

You're right. 4 is in fact not the value of Pi.
The problem is that the denominator variable is an int so 1/denomenator is int/int so the result is 0. That makes you exit the loop after just one iteration since pi == prevPi
Just change the denominator type to a double (or float) and you'll get the right answer.
Also, you don't need to write while(keepGoing == true). The variable keepGoing is already a boolean, you can write simply while(keepGoing)
Edit:
I enjoyed playing with this code, so here's a slightly shorter version that's more accurate due to the use of double. It also seems to converge quite a lot faster:
double pi = 0, denominator = 1, prevPi = 1;
while (pi != prevPi) {
prevPi = pi;
pi += (1 / denominator) - (1 / (denominator + 2));
denominator += 4;
}
return pi * 4;

The problem is that integer division results in an integer, not a float or double.
1 / 3 is 0.
To avoid this, you can switch to using a float for the denominator instead of an int.
float denominator = 1.0f;

Make your, all your operands are floating point types. Otherwise your result is an integer.
See Java Language Specifications:
If the promoted type is float or double, then floating-point arithmetic is performed.
Also, on most platforms you can use double without any performance penalty, but this is another topic. ;-)

Related

Java Double convert to Int round

I want to convert a double value to int when and only when 2 numbers after the dot are 0.
Example
double x = 25.001
You can use this :
double x = 25.001;
int i = (int) x;
System.out.println(x);//Input
if (x - i <= 0.01) {
x = (int) x;
}
System.out.println(x);//Output
RESULT
Input Output
25.001 25.0
25.011 25.011
If you want to use a second variable you can use :
int y = 0;
if (x - i <= 0.01) {
y = (int) x;
}
Note
But note, in case your input is not correct, you will always get 0, i like the first solution it is good then the second.
if(x-Integer.parseInt(x)>=0.001)
//Convert here
That rounded number you then cannot store in a double, as a double is always an approximation of a real value - of a series of a (negative) power of 2.
So you should go for BigDecimal as many do that want to do financial software.
If you did something like:
double adjustWhenCloseToInt(double x) {
long n = Math.round(x); // Could overflow for large doubles
if (Math.abs(x - n) < 0.01) {
x = n;
}
return x;
}
A simple
x = adjustWhenCloseToInt(x);
System.out.print(x);
Could still print 0.00000001 or such.
The solution there is
System.out.printf("%.2f", x);
Or better use a localized MessageFormat (thousand separators and such).
As floating point always bears rounding errors, I would in general go for BigDecimal, though it is a circumstantial class to use. Take care to use String constructors:
new BigDecimal("3.99");
As they then can maintain a precision of 2.

Diving floats - strange results [duplicate]

Here is my code. For some reason my BMI is not calculated correctly.
When I check the output on a calculator for this : (10/((10/100)^2))) I get 1000, but in my program, I get 5. I'm not sure what I am doing wrong. Here is my code:
import javax.swing.*;
public class BMI {
public static void main(String args[]) {
int height;
int weight;
String getweight;
getweight = JOptionPane.showInputDialog(null, "Please enter your weight in Kilograms");
String getheight;
getheight = JOptionPane.showInputDialog(null, "Please enter your height in Centimeters");
weight = Integer.parseInt(getweight);
height = Integer.parseInt(getheight);
double bmi;
bmi = (weight/((height/100)^2));
JOptionPane.showMessageDialog(null, "Your BMI is: " + bmi);
}
}
^ in java does not mean to raise to a power. It means XOR.
You can use java's Math.pow()
And you might want to consider using double instead of int—that is:
double height;
double weight;
Note that 199/100 evaluates to 1.
we can use
Math.pow(2, 4);
this mean 2 to the power 4 (2^4)
answer = 16
^ is not the operator you want. You are looking for the pow method of java.lang.Math.
You can use Math.pow(value, power).
Example:
Math.pow(23, 5); // 23 to the fifth power
Your calculation is likely the culprit. Try using:
bmi = weight / Math.pow(height / 100.0, 2.0);
Because both height and 100 are integers, you were likely getting the wrong answer when dividing. However, 100.0 is a double. I suggest you make weight a double as well. Also, the ^ operator is not for powers. Use the Math.pow() method instead.
Too late for the OP of course, but still...
Rearranging the expression as:
int bmi = (10000 * weight) / (height * height)
Eliminates all the floating point, and converts a division by a constant to a multiplication, which should execute faster. Integer precision is probably adequate for this application, but if it is not then:
double bmi = (10000.0 * weight) / (height * height)
would still be an improvement.
You should use below method-
Math.pow(double a, double b)
From (https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html#pow-double-double-)
Returns the value of the first argument raised to the power of the second argument.
int weight=10;
int height=10;
double bmi;
bmi = weight / Math.pow(height / 100.0, 2.0);
System.out.println("bmi"+(bmi));
double result = bmi * 100;
result = Math.round(result);
result = result / 100;
System.out.println("result"+result);
1) We usually do not use int data types to height, weight, distance,
temperature etc.(variables which can have decimal points)
Therefore height, weight should be double or float.
but double is more accurate than float when you have more decimal points
2) And instead of ^, you can change that calculation as below using Math.pow()
bmi = (weight/(Math.pow(height/100, 2)));
3) Math.pow() method has below definition
Math.pow(double var_1, double var_2);
Example:
i) Math.pow(8, 2) is produced 64 (8 to the power 2)
ii) Math.pow(8.2, 2.1) is produced 82.986813689753 (8.2 to the power 2.1)
I did the benchmarking with Math.pow(x,2) and x*x,
the result is that Math.pow() is easily forty times slower than manually multiplying it by itself, so i don't recommend it for anything where a little bit of performance is required.
Here's the results:
proof_of_work: 19.284756867003345
time for Math.pow(x,2) in ns: 35143
proof_of_work: 19.284756867003345
time for x*x in ns: 884
manual calculation is 39 times faster
and here's the test-code
double r1 = 4.391441320;
long multiply_d1 = System.nanoTime();
double multiply_dr = Math.pow(r1,2);
long multiply_d2 = System.nanoTime();
System.out.println(("proof_of_work: ") + (multiply_dr));
System.out.println(("time for Math.pow(x,2) in ns: ") + (multiply_d2 - multiply_d1));
long multiply_t1 = System.nanoTime();
double multiply_tr = r1*r1;
long multiply_t2 = System.nanoTime();
System.out.println(("proof_of_work: ") + (multiply_tr));
System.out.println(("time for x*x in ns: ") + (multiply_t2 - multiply_t1));
System.out.println(("manual calculation is ") + ((multiply_d2 - multiply_d1) / (multiply_t2 - multiply_t1)) + (" times faster"));
Most efficient solution is
public Float fastPow(Float number, Integer power) {
if (power == 0) {
return 1.0f;
} else if (power % 2 == 1) {
return fastPow(number, power - 1) * number;
} else {
return fastPow(number * number, power / 2);
}
}
Let A is our number and N our power. Then A^2^N = (A^2)^N. And A^N = (A^2)^N/2. The function above reflects this relationship.

Why does calculating pi using a loop not work correctly?

We got an assignment where we have to calculate the value of pi using the formula pi/4=1-1/3+1/5-1/7+1/9-1/11...(using 100 terms) but it doesn't seem to run the while-loop for some reason. We're students who have no prior experience of writing code and are just starting.
double pi = 1;
int count = 0;
int n = 3;
while (count < 100) {
if ((count&1) == 0) {
pi = pi - 1 / n;
} else {
pi = pi + 1 / n;
}
n = n + 2;
count++;
}
out.print(pi*4); //why is it printing out pi=1?????
The problem is you do not type cast. pi is double but 1/n returns int, since both the denominator and numerator are integers. This happens in JAVA. Basically, every time, 1/n which is actually fractional, returns 0 (int) for every n > 1 due to lack of type casting. So pi's value is always 1 and in the end pi*4 displays 4.0. So you have to convert (cast) the numerator or the denominator as fractional (double) to make 1/n fractional.
To solve the problem, change the statements
pi = pi + 1 / n;
pi = pi - 1 / n;
to
pi = pi + 1.0 / (double) n;
pi = pi - 1.0 / (double) n;
This displays the output as 3.1514934010709914.

java compute pi to 6 significant figurs

I'm having trouble with this program, we are supposed to compute pi to six significant figures, WITHOUT ROUNDING and WITHOUT using math library constant, the program should also show the number of iterations it took to reach 6 sig fig accuracy as well as the math constant in the output, so far I'm just trying to get my head around computing pi, I'm completely lost on how to get six 6 figs with or without rounding, not to mention how to iterate how many iterations it took to reach 6 sig figs pls help.
"Write an algorithm and program to compute π, using the formula described in the text PI/4 =1-(1/3)+(1/5)-(1/7)+(1/9)...." Output will include your computed value for π, the math library constant expected value for π and the number of iterations it took to reach six-significant digit accuracy. The number of iterations could exceed 250,000. Make your output clean and easy to read for comparing results.
This is the code I have so far to compute pi but even this I'm not sure is right.
public static void main(String[] args) throws Exception {
Double pi=1.0;
int s=1;
for (double j=3.0; j<100.0; j=j+2)
{
if (s % 2 == 0)
pi = pi + (1/j);
else
pi = pi - (1/j);
s = s + 1;
}
System.out.println(4*pi);
So there is presumably a way to make an a priori estimate of error using the alternating series theorem. But suppose you do not know the theorem or trust your math (if you do, just change 100.0 above to the right number. 800000.0 as estimated above would work, just barely). Here is something a little safer, perhaps, though it might be better to check the goodness of the estimate only every 1000 times through the loop, not each time?
Double pi=1.0; Boolean closeEnough=false;
int s=1;
for (double j=3.0; (!closeEnough); j=j+2)
{
if (s % 2 == 0)
pi = pi + (1/j);
else
pi = pi - (1/j);
if (Math.abs(4/(j+2))<0.000005)
closeEnough=true;
s = s + 1;
}
Ideally you should encapsulate your calculation in a class:
public class PI {
private double estimate = 1.0;
private int iteration = 0;
public double getEstimate() {
return 4 * estimate;
}
public void iterate() {
double ratio = 1.0 / (iteration * 2 + 3);
if (iteration % 2 == 0)
estimate -= ratio;
else
estimate += ratio;
iteration++;
}
}
Then the loop becomes pretty trivial:
PI pi = new PI();
while (Math.round(pi.getEstimate() * 1e5) != Math.round(Math.PI * 1e5))
pi.iterate();
For me this took 130,657 iterations
consider
String piStr = "3.14159";
Double pi=1.0;
int s=1;
double j=3.0;
String lcl = "";
String upToNCharacters = "";
while (true)
{
if (s % 2 == 0)
pi = pi + (1/j);
else
pi = pi - (1/j);
s = s + 1;
j=j+2;
lcl = "" + 4 * pi;
upToNCharacters = lcl.substring(0, Math.min(lcl.length(), 7));
if (upToNCharacters.equals(piStr)) {
break;
}
}
System.out.println(upToNCharacters);
System.out.println("after " + s);
output
3.14159
after 136121

Recover the original number from a float

Numbers are being stored in a database (out of my control) as floats/doubles etc.
When I pull them out they are damaged - for example 0.1 will come out (when formatted) as 0.100000001490116119384765625.
Is there a reliable way to recover these numbers?
I have tried new BigDecimal(((Number) o).doubleValue()) and BigDecimal.valueOf(((Number) o).doubleValue()) but these do not work. I still get the damaged result.
I am aware that I could make assumptions on the number of decimal places and round them but this will break for numbers that are deliberately 0.33333333333 for example.
Is there a simple method that will work for most rationals?
I suppose I am asking is there a simple way of finding the most minimal rational number that is within a small delta of a float number?.
you can store the numbers in the database as String and on the retrieval just parseDouble() them. This way the number wont be damaged, it will be same as you store there.
is there a simple way of finding a rational number that is within 0.00001 of a float number?.
This is called rounding.
double d = ((Number) o).doubleValue();
double d2 = Math.round(d * 1e5) / 1e5;
BigDecimal bd = BigDecimal.valueOf(d2);
or you can use BigDecimal to perform the rounding (I avoid using BigDecimal as it is needelessly slow once you know how to use rounding of doubles)
double d = ((Number) o).doubleValue();
BigDecimal bd = BigDecimal.valueOf(d).setScale(5, RoundingMode.HALF_UP);
Note: never use new BigDecimal(double) unless you understand what it does. Most likely BigDecial.valueOf(double) is what you wanted.
Here's the bludgeon way I have done it - I would welcome a more elegant solution.
I chose an implementation of Rational that had a mediant method ready-made for me.
I refactored it to use long instead of int and then added:
// Default delta to apply.
public static final double DELTA = 0.000001;
public static Rational valueOf(double dbl) {
return valueOf(dbl, DELTA);
}
// Create a good rational for the value within the delta supplied.
public static Rational valueOf(double dbl, double delta) {
// Primary checks.
if ( delta <= 0.0 ) {
throw new IllegalArgumentException("Delta must be > 0.0");
}
// Remove the integral part.
long integral = (long) Math.floor(dbl);
dbl -= integral;
// The value we are looking for.
final Rational d = new Rational((long) ((dbl) / delta), (long) (1 / delta));
// Min value = d - delta.
final Rational min = new Rational((long) ((dbl - delta) / delta), (long) (1 / delta));
// Max value = d + delta.
final Rational max = new Rational((long) ((dbl + delta) / delta), (long) (1 / delta));
// Start the fairey sequence.
Rational l = ZERO;
Rational h = ONE;
Rational found = null;
// Keep slicing until we arrive within the delta range.
do {
// Either between min and max -> found it.
if (found == null && min.compareTo(l) <= 0 && max.compareTo(l) >= 0) {
found = l;
}
if (found == null && min.compareTo(h) <= 0 && max.compareTo(h) >= 0) {
found = h;
}
if (found == null) {
// Make the mediant.
Rational m = mediant(l, h);
// Replace either l or h with mediant.
if (m.compareTo(d) < 0) {
l = m;
} else {
h = m;
}
}
} while (found == null);
// Bring back the sign and the integral.
if (integral != 0) {
found = found.plus(new Rational(integral, 1));
}
// That's me.
return found;
}
public BigDecimal toBigDecimal() {
// Do it to just 4 decimal places.
return toBigDecimal(4);
}
public BigDecimal toBigDecimal(int digits) {
// Do it to n decimal places.
return new BigDecimal(num).divide(new BigDecimal(den), digits, RoundingMode.DOWN).stripTrailingZeros();
}
Essentially - the algorithm starts with a range of 0-1. At each iteration I check to see if either end of the range falls between my d-delta - d+delta range. If it does we've found an answer.
If no answer is found we take the mediant of the two limits and replace one of the limits with it. The limit to replace is chosen to ensure the limits surround d at all times.
This is essentially doing a binary-chop search between 0 and 1 to find the first rational that falls within the desired range.
Mathematically I climb down the Stern-Brocot Tree choosing the branch that keeps me enclosing the desired number until I fall into the desired delta.
NB: I have not finished my testing but it certainly finds 1/10 for my input of 0.100000001490116119384765625 and 1/3 for 1.0/3.0 and the classic 355/113 for π.

Categories

Resources