In order to emulate Excel's rate function, I'm using the Apache POI rate function I grabbed from the svn:
private double calculateRate(double nper, double pmt, double pv, double fv, double type, double guess) {
//FROM MS http://office.microsoft.com/en-us/excel-help/rate-HP005209232.aspx
int FINANCIAL_MAX_ITERATIONS = 20; //Bet accuracy with 128
double FINANCIAL_PRECISION = 0.0000001; //1.0e-8
double y, y0, y1, x0, x1 = 0, f = 0, i = 0;
double rate = guess;
if (Math.abs(rate) < FINANCIAL_PRECISION) {
y = pv * (1 + nper * rate) + pmt * (1 + rate * type) * nper + fv;
}
else {
f = Math.exp(nper * Math.log(1 + rate));
y = pv * f + pmt * (1 / rate + type) * (f - 1) + fv;
}
y0 = pv + pmt * nper + fv;
y1 = pv * f + pmt * (1 / rate + type) * (f - 1) + fv;
// Find root by the Newton secant method
i = x0 = 0.0;
x1 = rate;
while ((Math.abs(y0 - y1) > FINANCIAL_PRECISION) && (i < FINANCIAL_MAX_ITERATIONS)) {
rate = (y1 * x0 - y0 * x1) / (y1 - y0);
x0 = x1;
x1 = rate;
if (Math.abs(rate) < FINANCIAL_PRECISION) {
y = pv * (1 + nper * rate) + pmt * (1 + rate * type) * nper + fv;
}
else {
f = Math.exp(nper * Math.log(1 + rate));
y = pv * f + pmt * (1 / rate + type) * (f - 1) + fv;
}
y0 = y1;
y1 = y;
++i;
}
return rate;
}
For calculateRate(120, 28.1, -2400, 0, 0, 0.1)), the output is the same as Excel: 0.599
But if I try the same calculation, this time with the values:
calculateRate(360, 15.9, -2400, 0, 0, 0.1))
In Excel I get 0.580, and the program returns -1.1500428517726355. Any hints?
There are a bunch of things that are wrong with this code that you have pasted in your question.
It assumes that a rate is always found (not true) and makes no provision for instances when a rate is not found.
Some of the statements will throw an error which could have been avoided by using a more appropriate programming statement. For instance, take the following statement from your code:
f = Math.exp(nper * Math.log(1 + rate));
This will throw an error when attempting to find Log of a negative or zero value. It could have been rewritten as
f = Math.pow(1 + rate, nper);
The comment in iterative calculations states that it is programming the secant method, yet the iterative calculations are checked for convergence of the wrong variable. It is testing for convergence of a future value when it should be testing for convergence of the interest rate.
I copy pasted your code in Notepad and removed the variable declaration of Java and replaced these with JavaScript variable declarations to test the code with your sample data. And just as I said, the code stops at the second iteration since the difference of future values goes out of error bound and since there is no test in place to see whether a rate is found, the code returns the interest rate as is and one which is wrong.
I am not sure why this code works in instances where it does report a correct rate as is the case with first data set. I would suggest re-coding of the function in a correct manner.
public double rate(double nper, double pmt, double pv)
{
//System.out.println("function rate : " + nper + " " + pmt + " pv " + pv);
double error = 0.0000001;
double high = 1.00;
double low = 0.00;
double rate = (2.0 * (nper * pmt - pv)) / (pv * nper);
while(true) {
// Check for error margin
double calc = Math.pow(1 + rate, nper);
calc = (rate * calc) / (calc - 1.0);
calc -= pmt / pv;
if (calc > error) {
// Guess is too high, lower the guess
high = rate;
rate = (high + low) / 2;
}
else if (calc < -error) {
// Guess is too low, higher the guess.
low = rate;
rate = (high + low) / 2;
}
else {
// Acceptable guess
break;
}
}
//System.out.println("Rate : " + rate);
return rate;
}
Example: =RATE(60, 2112500, 65000000) returns 0.025198; the same with Excel (correct).
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I need help implementing my working 4th-Order Runge-Kutta method for solving Newton's Cooling Law. Since time (t) is introduced with this problem, I am confused on the placings for the given conditions. Here is what's given: time interval begins t = 0 to t = 20 (in seconds), object temp = 300, ambient temp = 70, time increment is .1, and constant of proportionality = 0.19
public class RungeKutta {
public static double NewtonsCoolingLaw(double objectTemp,double ambientTemp)
{
double k = 0.19;
return -k * (objectTemp - ambientTemp);
}
public static void main(String[] args) {
double result = 0.0;
double initialObjectTemp = 300.0, givenAmbientTemp = 70.0;
double deltaX = (20.0 - 0)/10000;
for(double t = 0.0; t <= 20.0; t += .1)
{
double k1 = deltaX * NewtonsLaw(initialObjectTemp,givenAmbientTemp);
double k2 = deltaX * NewtonsLaw(initialObjectTemp + (deltaX/2.0),givenAmbientTemp + (k1/2.0));
double k3 = deltaX * NewtonsLaw(initialObjectTemp + (deltaX/2.0), givenAmbientTemp + (k2/2.0));
double k4 = deltaX * NewtonsLaw(initialObjectTemp + deltaX, givenAmbientTemp + k3);
givenAmbientTemp = givenAmbientTemp + (1.0/6.0) * (k1 + (2.0 * k2) + (2.0 * k3) + k4);
result = givenAmbientTemp;
}
System.out.println("The approx. object temp after 20 seconds is: " + result);
}
}
Bellow is my RK4 method for solving ODEs. In the code below, I solve the ODE y' = y - x to approximate y(1.005) given that y(1) = 10 and delta x = 0.001
public class RungeKutta {
public static double functionXnYn(double x,double y)
{
return y-x;
}
public static void main(String[] args) {
double deltaX = (1.005 - 0)/10000;
double y = 10.0;
double result = 0.0;
for(double x = 1.0; x <= 1.005; x = x + deltaX)
{
double k1 = deltaX * functionXnYn(x,y);
double k2 = deltaX * functionXnYn(x + (deltaX/2.0),y + (k1/2.0));
double k3 = deltaX * functionXnYn(x + (deltaX/2.0), y + (k2/2.0));
double k4 = deltaX * functionXnYn(x + deltaX, y + k3);
y = y + (1.0/6.0) * (k1 + (2.0 * k2) + (2.0 * k3) + k4);
result = y;
}
System.out.println("The value of y(1.005) is: " + result);
}
}
Based on the formula T(t) = Ts + (T0 - Ts) * e^(-k*t) I should have an approximation of 75.1 for solving Newton's DE. Ts = ambient temp, T0 = object initial temp, t = 20 (seconds elapsed), and k = .19 constant of proportionality
I'm guessing (but not really hard) that the ODE you are trying to solve is
dT(t)/dt = -k*(T(t)-T_amb)
As you can see, the right side does not directly depend on the time.
As you make no attempts to code for a system, it is likely that the ambient temperature T_amb is a constant. Thus moving the constants around and using consistent function names and returning the ODE function arguments to the format time, state variable
public class RungeKutta {
public static double CoolingLaw(double time, double objectTemp)
{
double k = 0.19, ambientTemp = 70.0;
return -k * (objectTemp - ambientTemp);
}
public static void main(String[] args) {
double result = 0.0;
double objectTemp = 300.0;
double dt = 0.1
for(double t = 0.0; t <= 20.0; t += dt)
{
double k1 = dt * CoolingLaw(t, objectTemp);
double k2 = dt * CoolingLaw(t + (dt/2.0), objectTemp + (k1/2.0));
double k3 = dt * CoolingLaw(t + (dt/2.0), objectTemp + (k2/2.0));
double k4 = dt * CoolingLaw(t + dt, objectTemp + k3);
objectTemp = objectTemp + (1.0/6.0) * (k1 + (2.0 * k2) + (2.0 * k3) + k4);
result = objectTemp;
}
System.out.println("The approx. object temp after 20 seconds is: " + result);
}
}
is supposed to calculate the coordinates of a projectile launched with respect to time (steps of 100ms), with a linear equation, and it outputs linear numbers, but if i plot this equation with CalcMe.com (math tool) it makes a parabolic plot
InVel = Double.parseDouble(jTextField1.getText());
g = Double.parseDouble(jTextField8.getText());
y = 1;
while(y >= -1) {
t += 100;
x = InVel * TimeUnit.MILLISECONDS.toSeconds(t) * Math.cos(45);
y = InVel * TimeUnit.MILLISECONDS.toSeconds(t) * Math.sin(45) - (1 / 2) * g * Math.pow(TimeUnit.MILLISECONDS.toSeconds(t), 2);
//System.out.print(Double.toString(x));
//System.out.printf(" ");
System.out.print(Double.toString(y));
System.out.printf("%n");
}
jTextField6.setText(Double.toString(x));
the code is in java
g is constant (9.8)
and invel is given by user so its constant too
g is the gravity and invel the initial velocity of the projectile
the equation is:x=invel*time*cos(45) and y=invel*time*sin(45)-(1/2)*g*t^2
anyone can help me?
Your milisecond to second value conversion method TimeUnit.MILLISECONDS.toSeconds(t) is the main fact. Its returning long value which one you are wanted double. Please take a look on below code. Probably its your answer. Just replace hard-coded value with your jTextField
public static void main(String[] args) {
double InVel = Double.parseDouble("10.555");
double g = Double.parseDouble("9.8");
double y = 1;
double x=0;
double t=0;
while(y >= -1) {
t += 100;
double timeInSeconds = (t / (double)1000) % (double)60;
x = InVel * timeInSeconds * Math.cos(45);
y = InVel * timeInSeconds * Math.sin(45) - ((double) 1 / (double) 2) * g * Math.pow(timeInSeconds, 2);
//System.out.print(Double.toString(x));
//System.out.printf(" ");
System.out.println("X = " + x + " Y = " + Double.toString(y));
System.out.printf("%n");
}
}
I have implemented the motion detection of user in my app by calculating its lat-long getting from googleAPIClient in which i am doing
1)get location of user in every 15 sec
2)the location before 15 sec and after 15 sec i am calculating the speed using formula mentioned below
`private double getSpeed(Location currentLocation, Location oldLocation) {
if (currentLocation != null && oldLocation != null) {
double newLat = currentLocation.getLatitude();
double newLon = currentLocation.getLongitude();
double oldLat = oldLocation.getLatitude();
double oldLon = oldLocation.getLongitude();
if (currentLocation.hasSpeed()) {
return currentLocation.getSpeed();
} else {
double radius = 6371000;
double dLat = Math.toRadians(newLat - oldLat);
double dLon = Math.toRadians(newLon - oldLon);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(Math.toRadians(newLat)) * Math.cos(Math.toRadians(oldLat)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.asin(Math.sqrt(a));
double distance = ((Math.round(radius * c)) * 36) /1.609344; // convert meter to km as m*60*60/s*1000 thn convert whole into miles;
CommonMethods.showLogs("BaseActivity.this", "getSpeed distance == " + distance);
double timeDifferent = (currentLocation.getTime() - oldLocation.getTime()) * 10; //convert mili sec to hr
CommonMethods.showLogs("BaseActivity.this", "getSpeed time == " + timeDifferent);
return distance / timeDifferent;
}
}
return 0;
}`
3) after that check if speed is more than 3mph than do my stuffs
4) it is working fine when tested in a car and bus but when tested in 2
wheeler it is not working properly some times it is some time it is not
i don't get the problem what is wrong in my case please help!!
Thanks!!
To be honest I've just started with programming but for the life of me I can't figure out where I'm wrong.
the math is:
10$ / 2 hours
tips per hour = 5 (i get 0.2)
waiter 1 pay = 10 (i get 0.4?)
screenshot
The Calculation in MainActivity:
double resultTotalHours = cWaiter1Hours + cWaiter2Hours + cWaiter3Hours + cWaiter4Hours;
double calcTipsPerHour = resultTotalHours / totalTips;
double resultBarsCut = (totalTips * (cBarCutInput / 100));
double resultTaxDeposit = resultTotalHours * 3;
double resultTipsPerHour = (totalTips - resultBarsCut - resultTaxDeposit) / resultTotalHours;
double resultWaiter1Pay = cWaiter1Hours * resultTipsPerHour;
double resultWaiter2Pay = cWaiter2Hours * resultTipsPerHour;
double resultWaiter3Pay = cWaiter3Hours * resultTipsPerHour;
double resultWaiter4Pay = cWaiter4Hours * resultTipsPerHour;
double resultWaiter1NoTax = cWaiter1Hours * calcTipsPerHour;
double resultWaiter2NoTax = cWaiter2Hours * calcTipsPerHour;
double resultWaiter3NoTax = cWaiter3Hours * calcTipsPerHour;
double resultWaiter4NoTax = cWaiter4Hours * calcTipsPerHour;
Casting the results to the TextViews:
if (calcTipsPerHour <= 30) {
totalHoursView.setText(Double.toString(resultTotalHours));
tipsPerHourView.setText(Double.toString(calcTipsPerHour));
barsCutView.setText(Double.toString(0));
taxDepositView.setText(Double.toString(0));
waiter1Pay.setText(Double.toString(resultWaiter1NoTax));
waiter2Pay.setText(Double.toString(resultWaiter2NoTax));
waiter3Pay.setText(Double.toString(resultWaiter3NoTax));
waiter4Pay.setText(Double.toString(resultWaiter4NoTax));
} else {
totalHoursView.setText(Double.toString(resultTotalHours));
tipsPerHourView.setText(Double.toString(resultTipsPerHour));
barsCutView.setText(Double.toString(resultBarsCut));
taxDepositView.setText(Double.toString(resultTaxDeposit));
waiter1Pay.setText(Double.toString(resultWaiter1Pay));
waiter2Pay.setText(Double.toString(resultWaiter2Pay));
waiter3Pay.setText(Double.toString(resultWaiter3Pay));
waiter4Pay.setText(Double.toString(resultWaiter4Pay));
}
The problem is here:
double calcTipsPerHour = resultTotalHours / totalTips;
This is currently doing 2 / 10 = 0.2.
You want to do the reciprocal:
double calcTipsPerHour = totalTips / resultTotalHours;
This should also fix your waiter's pay
You put hours in the numerator and tips in the denominator so you are getting the inverse of what you want: hours/tip
What you want is:
double calcTipsPerHour = totalTips / resultTotalHours;
I'm trying to update my variable startPreyPopulationSize and startPredatorPopulation size everytime it iterates but I'm not sure how to go about that since the bottom for loop affects the top one right?
//Equation to find out prey population size.
for(double rate = 0; rate <= numberOfPeriods; rate++) {
double partOne = startPreyPopulationSize / rate * (1 + RATE_A_BIRTH - RATE_B_PREDATION * (startPredatorPopulationSize / rate));
double updatedPreyPopulation = startPreyPopulationSize / (rate + 1);
updatedPreyPopulation = partOne;
System.out.printf("Period %5.0f: Prey Population %.2f; \n", rate, updatedPreyPopulation);
}
//Equation to find out predator population size.
for(double rate2 = 0; rate2 <= numberOfPeriods; rate2++) {
double partTwoEquation = startPredatorPopulationSize / rate2 * (1 - RATE_C_DEATHS + RATE_D_INCREASE * (startPreyPopulationSize / rate2));
double updatedPredatorPopulation = startPredatorPopulationSize / (rate2 + 1);
updatedPredatorPopulation = partTwoEquation;
System.out.printf("Period %5.0f: Predator Population %.2f; \n", rate2, updatedPredatorPopulation);
}
UPDATED CODE I'm basing my formula off of this if it helps http://i.imgur.com/rUQ774q.jpg I know my formula is off somehow.
//Equation to find out prey population size.
for(double rate = 0; rate < numberOfPeriods; rate++) {
partOne = startPreyPopulationSize / rate * (1 + RATE_A_BIRTH - RATE_B_PREDATION * (startPredatorPopulationSize / rate));
currentPreyPopulationSize = startPreyPopulationSize / (rate + 1);
currentPreyPopulationSize = partOne;
System.out.printf("Period %5.0f: Prey Population %.2f; \n", rate, currentPreyPopulationSize);
partTwoEquation = startPredatorPopulationSize / rate * (1 - RATE_C_DEATHS + RATE_D_INCREASE * (startPreyPopulationSize / rate));
currentPredatorPopulationSize = startPredatorPopulationSize / (rate + 1);
currentPredatorPopulationSize = partTwoEquation;
System.out.printf("Period %5.0f: Predator Population %.2f; \n", rate, currentPredatorPopulationSize);
startPreyPopulationSize = currentPreyPopulationSize;
startPredatorPopulationSize = currentPredatorPopulationSize;
}
Well your code for equations you provided is wrong.
1) In equation you have no division by rate, so it should look like
double currentPreyPopulationSize = startPreyPopulationSize * (1 + RATE_A_BIRTH - RATE_B_PREDATION * (startPredatorPopulationSize));
2) Also this division causing the -Infinity, because rate is 0 for the first iteration.