I'm trying to write own code for calculating approximation of rad angle. I works so far for only a specific range of numbers, but fails for large ones like 500 or so.
Additional subquestion: which is more efficient - calculating powers by Math.pow() or the current way of doing it - only multiplication operators.
private static double sin_range(double rad) {
double sin_rad = rad;
while (sin_rad > 2 * Math.PI) {
sin_rad -= 2 * Math.PI;
}
return sin_rad;
}
private static double approx(double rad, int err) {
double rad_in_range = sin_range(rad);
double sin = rad_in_range, r = rad_in_range;
int previous = 1, factorial = 1;
for (int i = 0; i < err; i++) {
factorial = (factorial * (previous + 1) * (previous + 2));
r *= rad * rad;
if ((i & 1) == 0) { //even
sin -= r / factorial;
} else { //odd
sin += r / factorial;
}
previous += 2;
}
return sin;
}
public static void main(String[] args) {
double approximated = approx(15, 5);
System.out.println(approximated + " = " + Math.sin(15));
}
Related
In my Pulse Wave generator, I need to find the value of cyclePoint (c) from cycleFrequency (f), cycleRange (r), minDutyCycle (m) and dutyCycle d.
Here is a formula that I made that finds the value of dutyCycle (d) from the other value
D = ((c/(f/2))r)+m
I'm not the best at algebra so I probably used the brackets wrong.
Here is my code
public class PulseGenerator extends SquareGenerator {
// constants
public static final double DEF_MIN_DUTY_CYCLE = 0.05;
public static final double DEF_MAX_DUTY_CYCLE = 0.95;
public static final double DEF_CYCLE_FREQ = 2;
public static final double DEF_HOLD_CYCLE = 0;
// instance variables
double minDutyCycle;
double maxDutyCycle;
double cycleFreq;
double holdCycle;
double dutyCycleRange;
boolean setDirection;
// constructor
public PulseGenerator(double amplitude, double frequency, int bitRate,
double duration, double dutyCycle, double minDutyCycle,
double maxDutyCycle, double cycleFreq, double holdCycle) {
super(amplitude, frequency, bitRate, duration, dutyCycle);
// sample data
squareSample = new int[sampleLength];
calculateAmpLimit();
this.dutyCycle = dutyCycle;
waveLength = sampleRate / this.frequency;
this.minDutyCycle = minDutyCycle;
this.maxDutyCycle = maxDutyCycle;
this.cycleFreq = cycleFreq * sampleRate;
this.holdCycle = holdCycle * sampleRate;
dutyCycleRange = this.maxDutyCycle - this.minDutyCycle;
setDirection = false;
}
// one arg cunstructor
public PulseGenerator(double frequency) {
this(AMPLITUDE, frequency, BIT_RATE, DURATION, DEF_DUTY_CYCLE,
DEF_MIN_DUTY_CYCLE, DEF_MAX_DUTY_CYCLE, DEF_CYCLE_FREQ,
DEF_HOLD_CYCLE);
}
// no args constructor
public PulseGenerator() {
this(AMPLITUDE, FREQUENCY, BIT_RATE, DURATION, DEF_DUTY_CYCLE,
DEF_MIN_DUTY_CYCLE, DEF_MAX_DUTY_CYCLE, DEF_CYCLE_FREQ,
DEF_HOLD_CYCLE);
}
// generate waveform method
#Override
public int[] generateWaveForm() {
// define the decimal j
double j = 1;
// define cycle point
// here is where I need to find the value of cycle point
int cyclePoint = (int)((dutyCycle * (cycleFreq / 2) - minDutyCycle) / dutyCycleRange);
System.out.println("Cycle point: " + cyclePoint);
// generate the actual waveform
for (int i = 0; i < sampleLength; i++, j++) {
double waveCycleRatio = waveLength * dutyCycle;
// same as square
// draws the wave
if (j - waveCycleRatio < 0.0) {
finePoint = 1.0;
} else if (j - waveCycleRatio >= 0.0
&& j - waveCycleRatio < 1) {
finePoint = 0 - (j - waveCycleRatio - 0.5) * 2;
} else if (j - waveLength < 0.0) {
finePoint = -1.0;
} else if (j - waveLength >= 0.0) {
finePoint = (j - waveLength - 0.5) * 2;
}
// checks if j is equal to wavelength
if (j == waveLength) {
j = 1;
} else if (j - waveLength > 0.0 && j - waveLength < 1.0) {
j = (j - waveLength);
}
point = (int)(finePoint * ampLimit);
squareSample[i] = point;
if (holdCycle > 0) {
holdCycle--;
} else {
// implementation of formula to find duty cycle
dutyCycle = (cyclePoint / (cycleFreq / 2) * dutyCycleRange)
+ minDutyCycle;
if (cyclePoint < cycleFreq / 2 && !setDirection) {
cyclePoint++;
} else if (cyclePoint >= cycleFreq / 2 && !setDirection) {
cyclePoint--;
setDirection = true;
} else if (cyclePoint > 0 && setDirection) {
cyclePoint--;
} else if (cyclePoint <= 0 && setDirection) {
cyclePoint++;
setDirection = false;
}
}
}
// return the sample data
return squareSample;
}
}
I believe this line is a bit off:
int cyclePoint = (int)((dutyCycle * (cycleFreq / 2) - minDutyCycle) / dutyCycleRange);
and it should be like:
int cyclePoint = (int)((cycleFreq / 2) * (dutyCycle - minDutyCycle) / dutyCycleRange);
This code line:
int cyclePoint = (int)((dutyCycle * (cycleFreq / 2) - minDutyCycle) / dutyCycleRange);
should be replaced with:
int cyclePoint = (int) (((dutyCycle - minDutyCycle) * cycleFreq) / (2 * dutyCycleRange));
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'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;
I want to know how to calculate this equation in Java considering that the exponent can be negative
equation example:
D_DL=10^((149.874-69.55-26.16 log_10(900)+13.82 log_10(60)+1.115)/([44.9-6.55 log_10(60)]))
Here I'm trying to calculate my exponent
double exposantD = ( Mapldl_s - 69.55 -( 26.16 * Math.log10(_BF_) )+ (13.82 * Math.log10(HB_)) + _ahm_) / (44.9 - (6.55 *Math.log10(HB_)));
I try with this function :
public static double powMyExpo(double base, double exponent) {
double result = 1;
if (exponent == 0) {
return result;
}
if (exponent < 0) {
return 1 / powMyExpo(base, exponent * -1);
}
for (int i = 1; i <= exponent; i++) {
result = result * base;
}
return result;
}
but always result = 1
Thanks
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;
}