Summing array values java - java

I'm feeding in an array of length 8 say if trials is 100 it might be of the form 93 5 2 0 0 0 0 0, but whatever the values I have in the array I only get 0.6 back. If anyone can see if I'm making a stupid error that would be great. I've tried it with a for loop but keep getting 0.6.
static void getMetric(int[]a, int trials){
double metric = 0;
int i =0;
while(i<8){
if(i==0){
double x = (a[0] / trials) - (2 / 15);
metric += Math.abs(x);
i++;
}
else if(i>0 && i<7){
double x = (a[i] / trials) - 0.1;
metric += Math.abs(x);
i++;
}
else{
double x = (a[7] / trials) - (2 / 15);
metric += Math.abs(x);
System.out.println(""+metric);
i++;
}
}
}

You use integer division ( 5 / 3 = 1; 2 / 15 = 0).
So instead of a[0] / trials, you should have a[0] / (double) trials;
Instead of 2 / 15 you should have 2 / 15.0 etc.

It looks like you need double-division and not int-division. Remember:
int a = 96;
int b = 100;
double c = a / b; //will be 0.0!
so the following program should do the same, but more correct, I think (and shorter):
static void getMetric(int[] a, int trials){
double metric = Math.abs((((double)a[0]) / trials) - (2 / 15));
for (int i = 1; i < 7; i++) {
metric += Math.abs((((double)a[i]) / trials) - 0.1);
}
metric += Math.abs((((double)a[7]) / trials) - (2 / 15));
System.out.println(""+metric);
}
and that one is even more reable and robust:
static void getMetric(int[] a, int trials){
double metric = calcMetricDiff(a[0], trials, 2.0 / 15.0);
for (int i = 1; i < a.length - 1; i++) {
metric += calcMetricDiff(a[i], trials, 0.1);
}
metric += calcMetricDiff(a[a.length-1], trials, 2.0 / 15.0);
System.out.println(""+metric);
}
private static double calcMetricDiff(double val, int trials, double diff) {
return Math.abs((val / trials) - diff);
}

Related

How to implement arctan function in Java?

Function to implement
Code
public class arctan {
public static double arctan(double x) {
double sum = 0;
int k = 0;
double arctan1 = (Math.pow(-1, k) * (Math.pow(x, 2 * k + 1) / (2 * k + 1)));
for (int i = k; i < 100; i++) {
sum =+ arctan1;
}
return (double) arctan1;
}
}
Issue
My program just gives back my x as output. I don't see the mistake I am doing.
You have to put double arctan1 = (Math.pow(-1, k) * (Math.pow(x, 2 * k + 1) / (2 * k + 1))); in the loop as well since that is what the Σ is doing in the formula.
You also didn't need to have a new variable i in the for loop in this case. Using k like the formula is fine.
So it would be like this instead:
public class arctan {
public static double arctan(double x) {
double sum = 0;
for (int k = 0; k < 100; i++) {
sum += (Math.pow(-1, k) * (Math.pow(x, 2 * k + 1) / (2 * k + 1)));
}
return sum;
}
}
What does the letter Σ (sum over) mean?
See Wikipedia about the mathematical sum-symbol (uppercase sigma in Greek alphabet): Σ.
In you case it is the sum over a range from k = 0 until k = infinite.
The sum of the term following the sigma.
Define it as function instead variable
The term following is implemented correctly by:
double arctan1 = (Math.pow(-1, k) * (Math.pow(x, 2 * k + 1) / (2 * k + 1)));
Extract it as function of k and x:
public static double arctan1(int k, double x) {
return ( Math.pow(-1, k) * (Math.pow(x, 2 * k + 1) / (2 * k + 1) ));
}
Because the calculation is depending on inputs k and x now, you can use it in your sum-over range of k:
// Note: the limit is 99 here, not infinite
for (int k = 0; k < 100; k++) {
sum += arctan1( k,x ); // increasing k used as input
}
Put it all together
// your "term following the sum-over" implemented by function arctan1(int k, double x)
public static double arctan(double x) {
double sum = 0;
// your loop to sum-up for increasing k
return sum;
}

Calculating the term for pi using Taylor series using Java

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.)

Java median. When I have an array with a pair number, the median I get isnt correct [duplicate]

This question already has answers here:
Division of integers in Java [duplicate]
(7 answers)
Closed 7 years ago.
public static double calcMedian(int[] array) {
int n = array.length;
int middle = n / 2;
double median=0;
for (int i = 0; i < n; i++) {
if ((n % 2) == 1) {
median = array[middle];
} else if((n % 2) == 0){
median = (array[middle-1] + array[middle]) / 2;
}
}
return median;
}
When I have an odd numbers of element I don't get the right median. For instance, if my array is [1 3 6 7 10 12], the median should be 6.5. What I get is 6. I can't understand why. Thanks in advance
Because you are dividing an int by an int, the result is also of type int, and the decimal part of the result (.5) is truncated.
To get a double result, cast either the dividend or divisor to a double before the division operation, like so:
median = (array[middle-1] + array[middle]) / ((double) 2);
or
median = ((double) (array[middle-1] + array[middle])) / 2;
You should change it to this (copy and paste ready, also tested and gives 6.5)
public static double calcMedian(int[] array) {
int n = array.length;
int middle = n / 2;
double median=0;
for (int i = 0; i < n; i++) {
if ((n % 2) == 1) {
median = array[middle];
} else if((n % 2) == 0){
median = ((double)(array[middle-1] + array[middle])) / 2;
}
}
return median;
}

Return how many terms are necessary entering a level of precision, e.g .001, to come within the specified precision of the value of PI?

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;

adding fractions using recursion e=1+1/1!+1/2!+1/3!+

I need to write a recursive method to compute the following series:
e = 1+1/1!+1/2!+1/3!+...
This is what I have so far.
public static void main(String[] args)
{ System.out.println("enter n :");
int n =scan.nextInt();
double h = fact(n);
System.out.println(" e = ");
}
public double fact(int n)
{
if (n == 1)
return 1;
else
return ???;
}
}
So, assuming the n input you're taking is the starting denominator for the smallest fraction you'd add...
(For example, given n = 10, you want to add 1 through 1/10)
Then you need to set up your method so that when you call fact(10), it's going to return the sum of 1/10 plus the result of fact(9), or more generically, 1/n + fact(1/n-1);
So, you're looking for something like this:
public double fact(int n) {
if (n < 0) {
return 0.0;
} else if (n == 0) {
return 1.0;
} else {
return (1.0/n + fact(n-1))
}
}
Also, please note the changes to the base cases. When n < 0, we just return 0.0, because if I recall correctly, the factorial of any negative number is always 0, right?
Meanwhile, the base case should be n==0, not n == 1. Your series starts with 1 + 1/1. Note that 1 is not 1/0 or 1/nothing, it's just 1/1. We can't return 1/n when n is 0. For the series to calculate correctly, we have to add the first return the first element of the series in the case of n = 0.
And keep in mind, as with all recursive functions, very large values of n will cause a stack overflow.
Here are a couple of resources:
Math is fun
"Yes you can! But you need to get into a subject called the "Gamma
Function", which is beyond this simple page.
Half Factorial
But I can tell you the factorial of half (½) is half of the square
root of pi = (½)√π, and so some "half-integer" factorials are:"
More specifically you want the Gamma Function
Apache commons has an implementation of this function.
Discussion on Math Exchange
And here is an implementation from Princeton
public class Gamma {
static double logGamma(double x) {
double tmp = (x - 0.5) * Math.log(x + 4.5) - (x + 4.5);
double ser = 1.0 + 76.18009173 / (x + 0) - 86.50532033 / (x + 1)
+ 24.01409822 / (x + 2) - 1.231739516 / (x + 3)
+ 0.00120858003 / (x + 4) - 0.00000536382 / (x + 5);
return tmp + Math.log(ser * Math.sqrt(2 * Math.PI));
}
static double gamma(double x) { return Math.exp(logGamma(x)); }
public static void main(String[] args) {
double x = Double.parseDouble(args[0]);
System.out.println("Gamma(" + x + ") = " + gamma(x));
System.out.println("log Gamma(" + x + ") = " + logGamma(x));
}
}
Calculating e^n recursively is very expensive. It is O(n^2) and it is hard to know when to stop. Instead I suggest you do it iteratively.
static final int runs = 20000;
static volatile int exp = 1;
static volatile int n = 18;
static volatile double dontOptimiseAway;
public static void main(String[] args) throws InterruptedException {
System.out.println("Math.exp(1)=" + Math.exp(1));
System.out.println("exp_iter(18)=" + exp_iter(18));
System.out.println("exp_recurse(18)=" + exp_recurse(18));
for (int t = 0; t < 3; t++) {
System.out.printf("exp(1), exp_iter(18), exp_recurse(18) took %,d / %,d / %,d ns on average%n",
timeMathExp(), timeExpIter(), timeExpRecurse());
}
}
public static long timeMathExp() {
long start = System.nanoTime();
for (int i = 0; i < runs; i++)
dontOptimiseAway = Math.exp(exp);
return (System.nanoTime() - start) / runs;
}
public static long timeExpIter() {
long start = System.nanoTime();
for (int i = 0; i < runs; i++)
dontOptimiseAway = exp_iter(n);
return (System.nanoTime() - start) / runs;
}
public static long timeExpRecurse() {
long start = System.nanoTime();
for (int i = 0; i < runs; i++)
dontOptimiseAway = exp_recurse(n);
return (System.nanoTime() - start) / runs;
}
public static double exp_iter(int n) {
double exp = 0, x = 1;
for (int i = 2; i <= n; i++)
exp += (x /= i);
return 2 + exp;
}
public static double exp_recurse(int n) {
return n <= 0 ? 1 : 1.0 / fact(n) + exp_recurse(n - 1);
}
public static double fact(int n) {
return n <= 1 ? 1 : n * fact(n - 1);
}
prints
Math.exp(1)=2.718281828459045
exp_iter(18)=2.718281828459045
exp_recurse(18)=2.7182818284590455
exp(1), exp_iter(18), exp_recurse(18) took 111 / 191 / 760 ns on average
exp(1), exp_iter(18), exp_recurse(18) took 75 / 78 / 558 ns on average
exp(1), exp_iter(18), exp_recurse(18) took 69 / 66 / 552 ns on average
write the code as below and call it from main class.
public static double recursiveFun(double value){
if (value==1)
return 1.0;
if (value==2){
return (1/(value-1) + 1/value);
}
else
return recursiveFun(value-1) + 1/value;
}

Categories