I want to use the for loop for my problem, not while. Is it possible to do the following?:
for(double i = 0; i < 10.0; i+0.25)
I want to add double values.
To prevent being bitten by artifacts of floating point arithmetic, you might want to use an integer loop variable and derive the floating point value you need inside your loop:
for (int n = 0; n <= 40; n++) {
double i = 0.25 * n;
// ...
}
You can use i += 0.25 instead.
James's answer caught the most obvious error. But there is a subtler (and IMO more instructive) issue, in that floating point values should not be compared for (un)equality.
That loop is prone to problems, use just a integer value and compute the double value inside the loop; or, less elegant, give yourself some margin: for(double i = 0; i < 9.99; i+=0.25)
Edit: the original comparison happens to work ok, because 0.25=1/4 is a power of 2. In any other case, it might not be exactly representable as a floating point number. An example of the (potential) problem:
for(double i = 0; i < 1.0; i += 0.1)
System.out.println(i);
prints 11 values:
0.0
0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999
for(double i = 0; i < 10.0; i+=0.25) {
//...
}
The added = indicates a shortcut for i = i + 0.25;
In
for (double i = 0f; i < 10.0f; i +=0.25f) {
System.out.println(i);
f indicates float
The added = indicates a shortcut for i = i + 0.25;
For integer.
We can use : for (int i = 0; i < a.length; i += 2)
for (int i = 0; i < a.length; i += 2) {
if (a[i] == a[i + 1]) {
continue;
}
num = a[i];
}
Same way we can do for other data types also.
private int getExponentNumber(double value){
String[] arr;
String strValue = String.valueOf(value);
if (strValue.contains("E")){
arr = strValue.split("E");
return Math.abs(Integer.parseInt(arr[1]));
}
else if (strValue.contains(".")){
arr = strValue.split("\\.");
return arr[1].length();
}
return 0;
}
private int getMinExponent(int start, int stop, int step){
int minExponent = Math.max(Math.abs(start), Math.abs(stop));
minExponent = Math.max(minExponent, Math.abs(step));
return minExponent;
}
double start = 0;
double stop = 1.362;
double step = 2E-2;
int startExp = getExponentNumber(start);
int stopExp = getExponentNumber(stop);
int stepExp = getExponentNumber(step);
int min = getMinExponent(startExp, stopExp, stepExp);
start *= Math.pow(10, min);
stop *= Math.pow(10, min);
step *= Math.pow(10, min);
for(int i = (int)start; i <= (int)stop; i += (int)step)
System.out.println(i/Math.pow(10, min));
Related
So I am required to recursively calculate e^x using a factored form of a Taylor series:
equation: e^x = 1 +x + (x^2)/2! + ... + ((x^n)/n!))
U(n) = U(n-1)*(x/n)
break point |U(n)| < eps
package lab2;
import java.util.Scanner;
public class Lab2 {
public static void main(String[] args) {
// TODO code application logic here
Scanner in = new Scanner(System.in);
System.out.println("Enter x: ");
int x = in.nextInt();
System.out.println("Enter 0 < e < 1: ");
double e = in.nextDouble();
double result = 1.0;
int n = 1;
double U = x / n;
while (Math.abs(U) >= e)
{
double fa = 1;
for (int i = 1; i <= n; i++)
fa *= i;
result += Math.pow(x, n) / fa;
U *= x / ++n;
}
System.out.println("e^x = " + result);
}
}
It works only x+1 times and then debug says U equals 0 and its our break point. I can't get why this happens. Can you please help me?
Since x and n are integer, dividing them will be done using integer division. Only after the division is down is the result promoted to a double in order to store in U. In order to perform floating point division you could either define x as a double or explicitly cast it when you divide:
double U = ((double) x) / n;
I am trying calculating the term for Pi using the Taylor series. I want to keep adding terms until the last value of term is less than 1e-17. I have set the program right now at term = 31 because after that there is no change Pi = 3.141592653589794 error = 8.88178e - 16.
public static double compPi()
{
int terms1 = 31;
int sg = 1, denom1 = 1;
double sum = 1.0, denom2 = 1.0;
for (int t = 2; t <= terms1; t++){
denom1 += 2; denom2 *= 3;
double term = 1.0/ (denom1 * denom2);
sg *= -1;
sum += sg * term;
}
double pi = Math.sqrt(12) * sum;
return pi;
}
As Louis Wasserman suggested you are running into precision limitations with doubles in Java. Consider using BigDecimals for your calculations for more precision.
The floating-point errors in your sum are adding up to that difference, simply reverse your iteration (t = 31..2, i.e. start by adding up the very small summands first) and the error goes away:
public static double compPiReversed()
{
int terms1 = 31;
int sg = -1;
double sum = 0;
for (int t = terms1; t >= 2; --t) {
int denom1 = 1 + (t-1) * 2;
double denom2 = Math.pow(3, t-1);
double term = 1.0 / (denom1 * denom2);
sg *= -1;
sum += sg * term;
}
sum += 1;
double pi = Math.sqrt(12) * sum;
return pi;
}
again the 31st summand won't actually contribute (try starting at terms1 = 30, don't forget to change the sign sg = 1, too.)
I am trying to write a program which asks the user for a series of positive values and computes the mean and standard deviation of those values having the input stop when the user enters -1. I seem to have the average part down however. I can't seem to get the standard deviation.
So far this is what I have.
import java.util.Scanner;
public class HW0402
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
double x;
double sum = 0;
double average = 0;
double dev = 0;
double var = 0;
double sqrx = 0;
int n = 0;
do
{
System.out.println("Enter positive values, enter -1 to end");
x = input.nextInt();
if (x == -1)
{
break;
}
sum += x;
n++;
average = sum / n;
sqrx += Math.pow(x-average,2);
var = sqrx / (n-1);
dev = Math.sqrt(var);
} while (x != -1);
System.out.println("Average: " + average);
System.out.println("Deviation: " + dev);
}
}
I seem to get odd results such as decimals when simply calculating sqrx += x- average
I'm new to java and haven't leaned alternatives to this problem, I would love it if someone pointed me in the right direction on what I should do, or explain what I did wrong.
Apologies ahead of time for any novice mistakes I made.
int n = 0;
int K = 0;
double Sum = 0;
double Sum_sqr = 0;
do {
System.out.println("Enter positive values, enter -1 to end");
x = input.nextInt();
if (x == -1)
{
break;
}
if ( n == 0 ) K = x;
n++;
Sum += (x - K);
Sum_sqr += (x - K) * (x - K);
} while (x != -1);
double mean = K + Sum / n;
double varPop = (Sum_sqr - (Sum*Sum)/n) / (n);
double varSample = (Sum_sqr - (Sum*Sum)/n) / (n-1);
double devPop = Math.sqrt(varPop);
double devSample = Math.sqrt(varSample);
Reference Wikipedia: Computing Shifted Data. Also, Population or Sample, makes a difference.
Problem: Interactively enter a level of precision, e.g., .001, and then report how many terms are necessary for each of these estimates to come within the specified precision of the value of pi.
My Solution So Far:
Current result does not terminate. The PIEstimator class driver is given. The problem lies inside the PIEstimates class. Some specific questions that I have:
How do you calculate Wallis PI and Leibniz PI in code? The ways for calculating each arithmetically for Wallis is:
pi/4 = (2/3)(4/3)(4/5)(6/5)(6/7)(8/7)(8/9)*...
and for Leibniz:
pi/4 = (1 - 1/3 + 1/5 - 1/7 + 1/9 ...)
Is the current logic of doing this code correct so far? Using a while loop to check if the respective PI calculation is within the limits, with a for loop inside continuing to run until the while requirements are met. Then there is a count that returns the number of times the loop repeated.
For .001, for example, how many terms does it take for each of these formulas to reach a value between 3.14059.. and 3.14259...
import java.util.Scanner;
public class PiEstimator {
public static void main(String[] args) {
System.out.println("Wallis vs Leibnitz:");
System.out.println("Terms needed to estimate pi");
System.out.println("Enter precision sought");
Scanner scan = new Scanner(System.in);
double tolerance = scan.nextDouble();
PiEstimates e = new PiEstimates(tolerance);
System.out.println("Wallis: " + e.wallisEstimate());
System.out.println("Leibnitz: " + e.leibnitzEstimate());
}
}
public class PiEstimates {
double n = 0.0;
double upperLim = 0;
double lowerLim = 0;
public PiEstimates(double tolerance) {
n = tolerance;
upperLim = Math.PI+n;
lowerLim = Math.PI-n;
}
public double wallisEstimate() {
double wallisPi = 4;
int count = 0;
while(wallisPi > upperLim || wallisPi < lowerLim) {
for (int i = 3; i <= n + 2; i += 2) {
wallisPi = wallisPi * ((i - 1) / i) * ((i + 1) / i);
}
count++;
}
return count;
}
public double leibnitzEstimate() {
int b = 1;
double leibnizPi = 0;
int count = 0;
while(leibnizPi > upperLim || leibnizPi < lowerLim) {
for (int i = 1; i < 1000; i += 2) {
leibnizPi += (4/i - 4/i+2);
}
b = -b;
count++;
}
return count;
}
}
At least one mistake in wallisEstimate
for (int i = 3; i <= n + 2; i += 2) {
should be count instead of n:
for (int i = 3; i <= count + 2; i += 2) {
... but still then the algorithm is wrong. This would be better:
public double wallisEstimate() {
double wallisPi = 4;
int count = 0;
int i = 3;
while(wallisPi > upperLim || wallisPi < lowerLim) {
wallisPi = wallisPi * ((i - 1) / i) * ((i + 1) / i);
count++;
i += 2;
}
return count;
}
Similarly, for the Leibniz function:
public double leibnitzEstimate() {
double leibnizPi = 0;
int count = 0;
int i = 1;
while(leibnizPi > upperLim || leibnizPi < lowerLim) {
leibnizPi += (4/i - 4/i+2);
count++;
i += 4;
}
return count;
}
For Leibnitz, I think the inner loop should only run count number of times:
for (int i = 1; i < count; i += 2) {
leibnizPi += (4/i - 4/i+2);
}
If it runs 1000 times every time you can't know when pi was in range.
If the while loops don't terminate, then they don't approach PI.
Wallis: pi/4 = (2/3)(4/3)(4/5)(6/5)(6/7)(8/7)(8/9)*...
The while loop would restart the for loop at i = 3 which would keep adding the same sequence of terms, rather than progressing along with the pattern.
Here's a draft of an alternative solution (no pun intended) based on the pattern of terms.
As you see, the numerators repeat, except for the 2. The divisors repeat aswell, but offset from the numerators: they increment in an alternating fashion.
This way you can actually count each individual terms, instead of pairs of them.
public double wallisEstimate() {
double wallisPi = 1;
int count = 0;
double numerator = 2;
double divisor = 3;
while(wallisPi > upperLim || wallisPi < lowerLim) {
wallisPi *= numerator / divisor;
if ( count++ & 1 == 0 )
numerator+=2;
else
divisor+=2;
}
return count;
}
There is one more change to make, and that is in the initialisation of upperLim and lowerLim. The algorithm approaches PI/2, so:
upperLim = (Math.PI + tolerance)/2;
lowerLim = (Math.PI - tolerance)/2;
Leibniz: pi/4 = (1 - 1/3 + 1/5 - 1/7 + 1/9 ...)
Here the for loop is also unwanted: at best, you will be counting increments of 2000 terms at a time.
The pattern becomes obvious if you write it like this:
1/1 - 1/3 + 1/5 - 1/7 ...
The divisor increments by 2 for every next term.
public double leibnitzEstimate() {
double leibnizPi = 0;
int divisor = 1;
int count = 0;
while(leibnizPi > upperLim || leibnizPi < lowerLim) {
leibnizPi += 1.0 / divisor;
divisor = -( divisor + 2 );
count++;
}
return count;
}
The update of leibnizPi can also be written like this:
leibnizPi += sign * 1.0 / divisor;
divisor += 2;
sign = -sign;
which is more clear, takes one more variable and one more instruction.
An update to the upperLim and lowerLim must be made here aswell: the algorithm approaches PI/4 (different from Leibniz!), so:
upperLim = (Math.PI + tolerance)/4;
lowerLim = (Math.PI - tolerance)/4;
I have started a java project for computing the n-th digit of pi, and decided to use the BBP algorithm.
In my output (in another class) I have been getting some weird math errors, and I don't know where it is from. So, I don't think I am putting the algorithm in the code correctly.
I got the algorithm from http://en.wikipedia.org/wiki/Bailey%E2%80%93Borwein%E2%80%93Plouffe_formula
Here's my code:
import java.lang.Math;
import java.lang.Math.*;
public class Pi
{
public static double getDigit(int n, int infinity)
{ int pow = 0;
double[] sums = new double[4];
int tot = 0;
int result = 0;
double fraction = 0;
for(int x = 0; x < 4; x++)
{
for(int k = 0; k < n; k++)
{
tot = 8 * k + 1;
if(x == 1)
tot += 3;
else if(x > 1)
tot++;
pow = n-k;
result = modular_pow(16, pow, tot);
sums[x] += (double)result / (double)tot;
}
for(int i = n + 1; i < infinity; i++)
{
tot = 8 * i + 1;
if(x == 1)
tot += 3;
else if(x > 1)
tot++;
fraction = Math.pow(16.0, (double)pow);
sums[x] += fraction / (double)tot;
}
}
return 4 * sums[0] - 2 * sums[1] - sums[2] - sums[3];
}
public static int modular_pow(int base, int exponent, int modulus)
{
int result = 1;
while(exponent > 0)
{
if (exponent % 2 == 1)
result = (result * base) % modulus;
exponent--;
base = (base * base) % modulus;
}
return result;
}
Thanks in advance.
Firstly, apologies for necro-ing an old post, but there is a severe lack of explanation of the BBP algorithm being applied meaningfully and so I think this might still be useful to some people who want to look into it.
Based on the Wikipedia article, the result you're returning needs to be stripped of its integer part (leaving the fractional part) and then multiplied by 16. This should leave the integer part as a representation of the nth hex digit of pi. I'll test it out tomorrow and see if that helps. Otherwise, great implementation, easy to understand and efficiently done.