trouble using an equation in a function - c++

Write a program that determines how far and for how long a time a rock will travel when you throw it off a cliff. Click here to copy the file toss.txt to your desktop (right click the file name and choose Save as). The file contains the height of the cliff in meters.
The program will then:
Open the file toss.txt and read the cliff height into a double-precision variable, then echo print the value of the cliff height to the screen with an appropriate label.
Ask the user for the angle at which the rock is thrown (90 degrees is straight up, and 0 degrees is straight forward), and the velocity at which the rock is thrown (in miles per hour).
Check to make sure the angle is greater than or equal to 0 and less than or equal to 90. If it is not, the program terminates and prints an appropriate error message to the screen.
Check to make sure the velocity is less than or equal to 100 mph and greater than or equal to 0 mph. If it is not, the program terminates and prints an appropriate error message to the screen.
If the angle and velocity are valid, the program completes the calculations as follows:
Converts miles per hour to meters per second.
Converts the angle to radians.
Calculates the time traveled using the following equations:
where
Calculates the distance traveled in the horizontal direction using:
Outputs the time and distance traveled in the horizontal direction to the screen with appropriate labels.
Prints an appropriate message telling the user if the distance traveled in the horizontal direction was greater than, less than, or equal to the height of the cliff.
/* This program */
using namespace std;
#include<iostream>
#include<cmath>
#include<iomanip>
#include<fstream>
int readit ();
int calcit (double, double, double);
int main()
{
readit ();
system ("pause");
return 0;
}
int readit ()
{
double hite, angl, v;
ifstream datain ( "toss.txt" );
datain >> hite;
cout << "The cliff height is " << hite << " meters"<< endl;
cout << "Enter the angle in degrees (from horizontal) the rock is thrown: "
<< endl;
cin >> angl;
if (angl>=0 && angl<=90)
{
cout << endl << "The angle you have entered is "<<angl<< endl <<endl;
}
else
{
cout << "The angle you have entered is not acceptable" << endl;
return 0;
}
cout << "Enter the velocity in mph the rock is thrown: " << endl;
cin >> v;
if (v>=0 && v<=100)
{
cout << endl << "The velocity at which the rock is thrown is "<<v<<
" mph" << endl << endl;
}
else
{
cout << "The velocity you have entered is not acceptable" << endl;
return 0;
}
calcit (hite, angl, v);
}
int calcit (double hite, double angl, double v)
{
double tyme, dist;
v = v * (1609.344/3600);
angl = angl*(M_PI/180);
tyme = -v*sin(angl) + (sqrt((v*sin(angl)*v*sin(angl)) + 2*9.8*hite)/9.8) + (2*(v*sin(angl))/9.8);
dist = (tyme * v) * cos(angl);
cout << tyme << " " << dist <<endl;
}
I am trying to get the correct time the rock is traveling before it hits the ground but i keep getting incorrect answers. I am not sure if i am turning the equation to figure out the time the rock will be in the air until impact into c++ language right. any have any ideas??? i really need to finish this damn project.

Starting from the equation for the y (height above 0) for the rock we have
y = h + v*sin(a)*t - g/2*t^2
which transforms into
g/2 T^2 - v*sin(a)*T - h == 0
when we solve for the final condition y(T)=0.
This yields
T = v*sin(a)/g + sqrt(v*sin(a)*v*sin(a) + 2*g*h)/g
I just can't figure out where the first part -v*sin(angl) in your equation comes from. Everything else looks just fine. So it seems not to be with your code but with the equation you started.

The equation you want is:
s =ut + 1/2 at^2
s = Total distance traveled. (Height of the cliff)
u = Starting velocity (In your case negative as you are throwing
away from the target. And take into account
that not all the starting velocity is away
from the target (eg angle 0 mean u = 0))
a = acceleration (9.81 m/s2)
t = time (The value you want to calculate).
Rearrange the formula to solve for t
To find the solution for t where s = 0...
This formula is you basic quadratic:
y = a.x^2 + b.x + c
Where:
x/y are variables.
a/b/c are constants.
The solution for a quadratic equation where y is 0 is:
x = [ -b ± sqrt(b^2 - 4ac) ] / 2a
Notice the ± symbol. There are actually two solutions to the problem.
You should be able to deduce which one is correct for you as the other
is probably negative.
In your particular case the map is:
x ==> t
y ==> 0
a ==> 1/2.g
b ==> u
c ==> -s

I would suggest a few things to "clean up" the code a bit:
If functions return int ensure that they do really return something. (main doesn't have to but other functions do).
Calculate v * sin(ang1) once then use it in your formula thereafter. Not only more efficient but will make your code clearer.
Like you have given Pi a "constant", do that with other numbers you are using like 9.8 (gravitational force?)

If you have a confusing formula in the code, just introduce more variable names until the meaning becomes obvious. So long as you don't reassign different values to the same variables, this will not make the program confusing.
int calcit (double hite_meters, double angl_deg, double v_mph)
{
double const gravity = 9.8;
double v_ms = v_mph * (1609.344/3600);
double angl_rad = angl_deg * (M_PI/180);
double v_vertical = v_ms * sin( angl_rad );
double time_up = v_vertical / gravity; // [m/s] / [m/s^2] = [s]
double time_down_over_cliff = time_up;
// use quadratic formula t = ( -v - ( v^2 - 4gd )^1/2 ) / 2g:
double time_under_cliff = ( - v_vertical
- sqrt( ( v_vertical * v_vertical )
- ( 4 * - gravity * hite_meters ) ) // negative gravity = down
) / ( 2 * - gravity ); // ( [m/s] + ([m/s]^2 - [m/s^2]*[m])^1/2 ) / [m/s^2]
// = [m/s] / [m/s^2] = [s]
double time_total = time_up + time_down_over_cliff + time_under_cliff;
double v_horizontal = v_ms * cos( angl_rad );
double dist_horizontal = v_ms * time_total;
cout << time_total << " " << dist_horizontal <<endl;
}
Every line of code produces a new, relevant piece of information. When converting to a new unit, I introduce a new variable with a new name. Formulas involving more than one unit get the unit types explained in a comment. This should help turn up unit conversion errors which otherwise I can't help you catch.
Writing this kind of code involves more typing, but the time saved on head-scratching and asking for help more than makes up for it.
The program itself is not any less efficient. More importantly, it may be easily modified, so it won't turn into an inefficient mess after a few revisions.

Related

Function for Newton's Method in C++

I am getting back into programming after twenty years. I was a good C programmer then, so I am jumping in with C++. For my first project, I am writing a function to calculate a cube root using Newton's Method.
Instead of converging on the answer, it just keeps approaching zero. Since it was so small, I figured it was easier to print out step by step values rather than use the debugger.
I am using Visual C++, with Visual Studio.
Here is the entire function:
double CalcCube(double xx, double guess)
{
int ii = 0;
double result, resbuff;
for (ii = 0; ii < 10; ii++)
{
resbuff = guess - (pow(guess,3) / (3*guess*guess));
cout << "Resbuff = " << resbuff << endl;
cout << "Guess = " << guess << endl;
guess = resbuff;
}
result = guess;
return result;
}`
`
Wrong equation used
Newton's Method finds the value of x such that f(x) = 0.
Code is solving 0 = x*x*x, which the answer is x = 0.
// x*x*x
// resbuff = guess - (pow(guess,3) / (3*guess*guess));
The zero being sought is the solution to 0 = y - x*x*x
resbuff = guess - (xx - pow(guess,3) / (3*guess*guess));
// y - x*x*x
The problem is the math:
pow(guess,3) / (3*guess*guess) = guess^3 / 3*guess^2 = guess/3
=> resbuf= guess - guess/3
So in each iteration you get an smaller value, tending to 0
The equation for computing cube root using the Newton Raphson method is (from https://socratic.org/questions/how-do-you-use-newton-s-method-to-approximate-the-value-of-cube-root)
xn1 = xn - (x - xn^3)/3*xn^2
By using
resbuff = guess - (pow(guess,3) / (3*guess*guess));
you are computing the cube root of zero. That's why you are getting zero as your answer.
Change that line to
resbuff = guess - (xx - pow(guess,3)) / (3*guess*guess));
to get the correct answer.

"Probability Based" Time Delay of Arrival Algorithm Producing Weird Results?

I've written the following algorithm designed to solve the Time Delay of Arrival problem through a "brute force" method. The problem is as follows: given the known locations of three receivers in a plane, and the propagating speed of some signal, determine the location of the signal source knowing only the times at which each receiver "saw" the signal.
The algorithm works by assuming the source to be within a 1000 x 1000 kilometre square area, and then iterating (with 1 km "resolution") over every possible location, calculating the time to travel to each receiver and determining which location matches most closely with the known delay of arrival between each receiver (so, for each location [x,y], I calculate the time to arrive to receivers 1, 2, and 3, then determine how close time to arrive at 1 - time to arrive at 2 is to the live data, and similarly for the combinations 1 - 3 and 2 - 3 (ignoring other possible combinations, for simplicity).
Here's the problem: it's highly unlikely each signal event is coming from the same direction. However, my code seems to suggest every event is at [0,0]. While it is technically possible that this is the case, it is far more likely that there is something wrong with my code, so for the purposes of this question let's assume that to be the case. Perhaps I've made some obvious mistake here?
#define c 299792
#define statn1x 3.00000
#define statn1y 3.60000
#define statn2x 2.10000
#define statn2y 2.10000
#define statn3x 0.96000
#define statn3y 3.60000
void findProb(double alpha, double gamma, double beta){
int x,y;
double thld = DBL_MAX;
for(int i = 0; i < 1000; ++i){
for(int j = 0; j < 1000; ++j){
double alphaEst = sqrt(pow(i-statn1x,2) + pow(j-statn1y,2)) / c;
double betaEst = sqrt(pow(i-statn1x,2) + pow(j-statn1y,2)) / c;
double gammaEst = sqrt(pow(i-statn1x,2) + pow(j-statn1y,2)) / c;
std::cout << i << "," << j << "\n";
if( std::max(std::max(fabs((alphaEst-betaEst) - alpha), fabs((alphaEst-gammaEst)-beta) ), fabs((betaEst-gammaEst)-gamma)) -
std::min(std::min(fabs((alphaEst-betaEst) - alpha), fabs((alphaEst-gammaEst)-beta) ), fabs((betaEst-gammaEst)-gamma)) < thld){
thld = std::max(std::max(fabs((alphaEst-betaEst) - alpha), fabs((alphaEst-gammaEst)-beta) ), fabs((betaEst-gammaEst)-gamma)) -
std::min(std::min(fabs((alphaEst-betaEst) - alpha), fabs((alphaEst-gammaEst)-beta) ), fabs((betaEst-gammaEst)-gamma));
x = i;
y = j;
}
}
}
//std::cout << x << "," << y << "\n";
}
void localize(){
ROOT::RDataFrame tdoa("D","./coincidences.root");
vector<double> alpha, beta, gamma;
tdoa.Foreach([&](double delay){ alpha.push_back(delay); },{"x"});
tdoa.Foreach([&](double delay){ beta.push_back(delay); },{"y"});
tdoa.Foreach([&](double delay){ gamma.push_back(delay); },{"z"});
int iter = std::min(std::min(alpha.size(), beta.size()), gamma.size());
for(int i = 0; i < iter; ++i){
findProb(alpha[i], beta[i], gamma[i]);
}
}
Note the terminology used in this project:
alpha refers to time to arrive (ttoa) at station 1 - ttoa station 2.
gamma refers to ttoa station 1 - ttoa station 3
beta refers to ttoa station 2 - ttoa station 3
alphaEst refers to the calculated estimated travel time from some location [x,y] to station 1
betaEst refers to the calculated estimated travel time from some [x,y] to station 2
... and likewise for gammaEst.
Note that I'm also working now to produce a smaller, reproducible example (if possible). I'll add that as soon as I can.
alphaEst, betaEst and gammaEst are assigned the same values.
betaEst = sqrt(pow(i-statn1x,2) + pow(j-statn1y,2)) / c
probably it should be
betaEst = sqrt(pow(i-statn2x,2) + pow(j-statn2y,2)) / c

Quaternion is flipping sign for very similar rotations?

Consider the following minimal working example:
#include <iostream>
#include <math.h>
#include <eigen3/Eigen/Dense>
int main() {
// Set the rotation matrices that give an example of the problem
Eigen::Matrix3d rotation_matrix_1, rotation_matrix_2;
rotation_matrix_1 << 0.15240781108708346, -0.98618841818279246, -0.064840288106743013,
-0.98826031445019891, -0.1527775600229907, 0.00075368177315370682,
-0.0106494132438156, 0.063964216524108775, -0.99789536976680049;
rotation_matrix_2 << -0.12448670851248633, -0.98805453458380521, -0.090836645094957508,
-0.99167686914182451, 0.12086367053038971, 0.044372968742129482,
-0.03286406263376359, 0.095604444636749664, -0.99487674792051639;
// Convert to Euler angles
Eigen::Vector3d euler_angles_1 = rotation_matrix_1.eulerAngles(2, 1, 0)*180.0f/M_PI;
Eigen::Vector3d euler_angles_2 = rotation_matrix_2.eulerAngles(2, 1, 0)*180.0f/M_PI;
// Convert to quaternion
Eigen::Quaternion<double> quaternion_1(rotation_matrix_1);
Eigen::Quaternion<double> quaternion_2(rotation_matrix_2);
// Print out results
std::cout << "Euler angles 1:\nyaw = " << euler_angles_1[0] << "\npitch = " << euler_angles_1[1] << "\nroll = " << euler_angles_1[2] << std::endl;
std::cout << "Quaternion 1:\nw = " << quaternion_1.w() << "\nx = " << quaternion_1.x() << "\ny = " << quaternion_1.y() << "\nz = " << quaternion_1.z() << std::endl;
std::cout << std::endl;
std::cout << "Euler angles 2:\nyaw = " << euler_angles_2[0] << "\npitch = " << euler_angles_2[1] << "\nroll = " << euler_angles_2[2] << std::endl;
std::cout << "Quaternion 2:\nw = " << quaternion_2.w() << "\nx = " << quaternion_2.x() << "\ny = " << quaternion_2.y() << "\nz = " << quaternion_2.z() << std::endl;
}
Whose output is:
Euler angles 1:
yaw = 98.767
pitch = 179.39
roll = -3.66759
Quaternion 1:
w = 0.020826
x = 0.758795
y = -0.650521
z = -0.0248716
Euler angles 2:
yaw = 82.845
pitch = 178.117
roll = -5.48908
Quaternion 2:
w = -0.0193663
x = -0.661348
y = 0.748369
z = 0.0467608
Both rotations are nearly identical (as given by the Euler angles). The expected behavior is that quaternion_2 will have values with same sign as quaternion_1, i.e. for the output to be:
Quaternion 2:
w = 0.0193663
x = 0.661348
y = -0.748369
z = -0.0467608
However, Eigen appears to "flip" the quaternion. I am aware that q and -q represent the same rotation - however, it is visually not appealing, and frankly annoying, that the quaternion would flip sign in each of its values. How can this be rectified for the general case (i.e. that the quaternion always preserves its "handedness", rather than flipping sign for certain rotations)?
When unit quaternions are used to represent 3d rotations, there are two ways to represent each actual rotation - and you can't avoid the 'negative' ones occuring without creating an artificial discontinuity in the space.
Unlike 2d rotations using complex numbers on a unit circle, the farthest point on the unit hypersphere from '0 rotation' has to be '360 degree rotation', not '180 degree'; since there is a 2d-space of possible 180 rotations which needs to be represented, whereas all 360-degree rotations are equivalent regardless of axis.
You can always 'canonicize' by changing the sign of the whole thing when the w component is negative.
There will still be cases where w = 0, these all represent rotations by 180 - e.g. (0,0,1,0) and (0,0,-1,0) represent the same rotation.
And, (0.01, 0.99995,0,0,0) and (-0.01, 0.99995,0,0) represent rotations very close together, but if you change the second one to the equivalent (0.01,-0.99995,0,0) then they are far apart in the 4d vector space.
So, practically speaking, you can still have a concern when you want to find the difference between two rotations to see how close they are. Canonicizing the two individually may not help;
you would generally want to flip signs as needed to make them as close as possible.
Or, to compare rotations q1,q2 : find the quaternion product q1 * q2.conj(); this gives the difference as a rotation quaternion; if it has w < 0, change its signs. For q1 and q2 close together (regardless of initial sign diffs) the result will always be fairly close to (1,0,0,0).
If you only want to check if they are within a certain angle 'th' of each other, you only need the real part of the result. This is equivalent to finding the dot product of q1,q2 (treating them as unit vectors in 4-space), then you check if the abs. value of the result >= cos(th/2).
Another way to find the relative angle: find the vector difference of the two unit vectors, and find the magnitude 'm' of that difference vector, (square root of the sum of squares) which will be in range [0,2]. Then find
th = 4*arcsin(m/2)
... and this will be 0 ... 2*pi.
In cases where m > sqrt(2), th > pi and you are getting the 'wrong side' result (also, the computation will have terrible numeric accuracy as m gets close to 2.0). So, in such cases, change one of the signs (i.e. make m the vector length of the sum of the inputs, rather than the difference); you will then have m <= sqrt(2), th <= pi.
For small m, the arcsin formula has the taylor series
th ~=~ 2*m + (m^3)/12 + ...
So, for small deltas, the relative rotation angle is approximately twice the magnitude of the vector difference (and this is numerically much more reliable than using an inverse-cosine-of-w when w is nearly 1).
The yaw angle is greater than 90 degrees for matrix 1, and less than 90 degrees for matrix 2. This will cause the cosine of the yaw angle to have different signs for the two, which is flipping your Quaternion.
A possible solution would be to check the w value of the Quaternion. If this is negative, you can flip it.
If you have access to the previous and the current quaternion reading, you can flip the sign of the current quaternion if it makes the distance between the quaternions in the 4D vector space smaller.
Flipping the sign will not affect the rotation, but it will ensure that there are no large jumps in 4D vector space when the rotation difference in rotation space (SO(3)) is small.
Quaternion avoidJumps(Quaternion q_Current, Quaternion q_Prev)
{
if ((q_Prev - q_Current).squaredNorm() < (q_Prev + q_Current).squaredNorm())
return -q_Current;
else
return q_Current;
}

Speeding up my code for a volume of a sphere (Nested while loops)

I'm trying to speed up my code for calculating the volume of a sphere (see code below).
This volume of the sphere is produced by calculating small volume segments, dv, and summing them into a volume, vol.
In reality this code is just a sanity check before I apply the calculations to other sphere like objects which will have symmetrical properties, hence I should be able to increase the speed of the code by calculating over a small volume and multiplying the end result.
Replace 360 and 180 in while (phid<=(360.0/adstep)) and while (thetad<=(180.0/adstep)) with 180 and 90 respectively and you quarter the calculations required meaning that you can simply multiply the final vol by 4.0.
This works if I set phi to and leave theta at 180, halving the calculations.
But it doesn't like it when I set theta to 90.
Ouput:
Phi 360, Theta 180
Actual Volume Calculated Volume % Difference
4.18879020478639053 4.18878971565348923 0.00001167718922403
Phi 180, Theta 180
4.18879020478639053 4.18878971565618219 0.00001167712493440
Phi 180, Theta 90
4.18879020478639053 4.18586538829648180 0.06987363946500515
You can see in the above that the first two calculations are near identical (I assume the difference is due to precision errors) while the last one gives significantly different results. Could the nested loops cause issues?
Any help would be appreciated as I haven't found anything in my research (google & stack overflow) to describe the problem I'm having.
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main()
{
double thetar, phir, maxr, vol, dv, vol2, arstep, adstep, rad, rad3, thetad, phid, ntheta, nphi;
cout << fixed << setprecision(17); // Set output precision to defined number of decimal places. Note Double has up to 15 decimal place accuracy
vol=0.0; // Initialise volume and set at zero
adstep=0.1; // Steps to rotate angles in degrees
arstep=(adstep/180.0)*M_PI; // Angle steps in radians
phid=1.0; // Phi in degrees starting at adstep
maxr = 1.0; // Radius of the sphere
// Loop to calculate volume
while (phid<=(360.0/adstep)) // Loop over Phi divided by adstep. This scales the loop to the desired number of calculations.
{
phir=((phid*adstep)/180.0)*M_PI; // Phi in radians
thetad=1.0; // Theta in degrees, reset to initial adstep value
while (thetad<=(180.0/adstep)) // Loop over Theta divided by adstep. Like Phi loop, this scales the loop to the desired number of calculations
{
thetar=((thetad*adstep)/180.0)*M_PI; // Convert theta degrees to radians
dv = ((maxr*maxr*maxr) * sin(thetar) * arstep * arstep) / 3.0; // Volume of current segment
vol += dv; // Summing all the dv value together to generate a global volume
thetad+=1.0; // Increase theta (degrees) by a single step
}
phid+=1.0; // Increase phi (degrees) by a single step
}
vol = vol*1.0; // Volume compensated for any reduction in phi and theta
rad3 = (3.0*vol)/(4.0*M_PI); // volume equivalent radius^3
rad = pow(rad3,(1.0/3.0)); // volume equivalent radius
vol2 = (4.0/3.0)*M_PI*(maxr*maxr*maxr); // Calculated volume of a sphere given initial maxr
// Diagnostic output
cout << vol2 << " " << vol << " " << ((vol2-vol)/vol)*100.0 << endl;
}
Edit: Corrected starting values of phid and thetad to 1.0
Edit 2:
I just wanted to update, for future viewers, that using the Kahan summation algorithm (https://en.wikipedia.org/wiki/Kahan_summation_algorithm) has virtually negated all my precision errors due to the summation of a small number onto a large number. There are other methods out there but this is one of the simplest and does the job I need it to.
For posterity this is the example psuedocode taken from the wikipedia page on the topic:
function KahanSum(input)
var sum = 0.0
var c = 0.0 // A running compensation for lost low-order bits.
for i = 1 to input.length do
var y = input[i] - c // So far, so good: c is zero.
var t = sum + y // Alas, sum is big, y small, so low-order digits of y are lost.
c = (t - sum) - y // (t - sum) recovers the high-order part of y; subtracting y recovers -(low part of y)
sum = t // Algebraically, c should always be zero. Beware overly-aggressive optimizing compilers!
// Next time around, the lost low part will be added to y in a fresh attempt.
return sum
As far as speed goes, I suspect (without having profiled it) that a lot of time is wasted converting between radians and degrees, and also computing all those sins. AFAICT, thetar loops through the same values during each iteration of the outer loop, so it would likely be more efficient to pre-compute sin(thetar) once before the main loop, and do a simple lookup in your inner loop.
As for numerical stability, as vol gets larger and larger than dv, you will start losing more and more precision as you go along. You would in principle get better results if you could store all the dvs in an array, then sum it using a divide and conquer approach rather than a linear pass. Then again I count (only) 6 480 000 total iteration, so I think a double accumulator (holding 15-17 significant base-10 digits) can actually handle losing 6-7 digits without much trouble.
Most likely, your problem is: exiting the loop 1 iteration before you want it. You should not compare floating-point numbers for equality. A quick way to fix it is adding a small constant, e.g.
while (thetad<(180.0/adstep)+1e-8)
This isn't a very thorough analysis but might give you some insight into the source of your error. In your code you are accumulating the value of 3240000 floating point numbers. As the value of vol increases, the ratio between dv and vol is increasing you are losing more and more precision in the addition.
A standard way to mitigate the loss of precision in accumulating many values to a single value (known as a reduction sum) is to perform the addition in blocks: for example, you could add together every 8 values and store them to an array, then add together every 8 values of that array, etc. until you are left with a single value. This is likely to get you a better result.
Also, it is worth considering that you are taking linear steps over a spherical surface, so you are not uniformly sampling your sphere. This is likely to affect your final result. One way of sampling the sphere uniformly is to take linear steps in the azimuthal angle phi from 0 to 360 degrees and take the acos of the range from -1 to 1 for your polar angle theta. See this link on sphere point-picking for a more detailed explanation.
First of all, I think, there are couple of errors in your function. I think both phid and thetad should be initialized to either 0 or 1.0.
Second, you can gain quite a bit by reducing the number of floating point multiplications.
In the code below, I moved the contents of your main function to volume1 and created a function volume2 that contains slightly optimized code.
#include <iostream>
#include <iomanip>
#include <cmath>
#include <ctime>
using namespace std;
void volume1(int numSteps)
{
double thetar, phir, maxr, vol, dv, vol2, arstep, adstep, rad, rad3, thetad, phid, ntheta, nphi;
cout << fixed << setprecision(17); // Set output precision to defined number of decimal places. Note Double has up to 15 decimal place accuracy
vol=0.0; // Initialise volume and set at zero
adstep=360.0/numSteps; // Steps to rotate angles in degrees
arstep=(adstep/180.0)*M_PI; // Angle steps in radians
phid=1.0; // Phi in degrees starting at adstep
maxr = 1.0; // Radius of the sphere
// Loop to calculate volume
while (phid<=(360.0/adstep)) // Loop over Phi divided by adstep. This scales the loop to the desired number of calculations.
{
phir=((phid*adstep)/180.0)*M_PI; // Phi in radians
thetad=1.0; // Theta in degrees, reset to initial adstep value
while (thetad<=(180.0/adstep)) // Loop over Theta divided by adstep. Like Phi loop, this scales the loop to the desired number of calculations
{
thetar=((thetad*adstep)/180.0)*M_PI; // Convert theta degrees to radians
dv = ((maxr*maxr*maxr) * sin(thetar) * arstep * arstep) / 3.0; // Volume of current segment
vol += dv; // Summing all the dv value together to generate a global volume
thetad+=1.0; // Increase theta (degrees) by a single step
}
phid+=1.0; // Increase phi (degrees) by a single step
}
vol = vol*1.0; // Volume compensated for any reduction in phi and theta
rad3 = (3.0*vol)/(4.0*M_PI); // volume equivalent radius^3
rad = pow(rad3,(1.0/3.0)); // volume equivalent radius
vol2 = (4.0/3.0)*M_PI*(maxr*maxr*maxr); // Calculated volume of a sphere given initial maxr
// Diagnostic output
cout << vol2 << " " << vol << " " << ((vol2-vol)/vol)*100.0 << endl << endl;
}
void volume2(int numSteps)
{
double thetar, maxr, vol, vol2, arstep, adstep, rad, rad3, thetad, phid, ntheta, nphi;
cout << fixed << setprecision(17); // Set output precision to defined number of decimal places. Note Double has up to 15 decimal place accuracy
vol=0.0; // Initialise volume and set at zero
adstep = 360.0/numSteps;
arstep=(adstep/180.0)*M_PI; // Angle steps in radians
maxr = 1.0; // Radius of the sphere
double maxRCube = maxr*maxr*maxr;
double arStepSquare = arstep*arstep;
double multiplier = maxRCube*arStepSquare/3.0;
// Loop to calculate volume
int step = 1;
for ( ; step <= numSteps; ++step )
{
int numInnerSteps = numSteps/2;
thetad = adstep; // Theta in degrees, reset to initial adstep value
for ( int innerStep = 1; innerStep <= numInnerSteps; ++innerStep )
{
thetar = innerStep*arstep;
vol += multiplier * sin(thetar); // Volume of current segment
}
}
vol = vol*1.0; // Volume compensated for any reduction in phi and theta
rad3 = (3.0*vol)/(4.0*M_PI); // volume equivalent radius^3
rad = pow(rad3,(1.0/3.0)); // volume equivalent radius
vol2 = (4.0/3.0)*M_PI*(maxr*maxr*maxr); // Calculated volume of a sphere given initial maxr
// Diagnostic output
cout << vol2 << " " << vol << " " << ((vol2-vol)/vol)*100.0 << endl << endl;
}
int main()
{
int numSteps = 3600;
clock_t start = clock();
volume1(numSteps);
clock_t end1 = clock();
volume2(numSteps);
clock_t end2 = clock();
std::cout << "CPU time used: " << 1000.0 * (end1-start) / CLOCKS_PER_SEC << " ms\n";
std::cout << "CPU time used: " << 1000.0 * (end2-end1) / CLOCKS_PER_SEC << " ms\n";
}
The output I get, using g++ 4.7.3:
4.18879020478639053 4.18762558892993564 0.02781088785811153
4.18879020478639053 4.18878914146923176 0.00002538483372773
CPU time used: 639.00000000000000000 ms
CPU time used: 359.00000000000000000 ms
That gets you an improvement of about 44%.

Why is my code producing an output of nan? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
My code is producing an output of nan.
I have looked around and I'm guessing it is as the equation is complicated from what I gather C++ doesn't recieve complicated equations too well.
But that doesnt seem right.
Here's my code:
#include <iostream>
#include <cmath>
using namespace std;
int main ()
{
int Backfill;
double SlopeAngleOfWall, AngleOfInternalFriction, AngleOfFrictionSoilAndWall, BackfillSlope, CoefficientOfActivePressure;
cout << "Retaining Wall Calculator \n";
cout << "Enter the slope angle of the wall, this is measured from the horizontal plane, therefor will be 90 degrees if the retaining wall is vertical \n";
cin >> SlopeAngleOfWall;
cout << "Enter the angle of internal friction \n";
cin >> AngleOfInternalFriction;
cout << "Enter the angle of friction between the soil and the wall \n";
cin >> AngleOfFrictionSoilAndWall;
cout << "Enter the angle of the backfill slope \n";
cin >> BackfillSlope;
/* To make sin function work is is typed (angle*pi/180) */
/* To make sin square work is is typesd (pow(sin (angle*pi/180), 2.0) */
/* To add a square root sqrt is used */
CoefficientOfActivePressure = (pow (sin ((SlopeAngleOfWall + AngleOfInternalFriction)*pi/180), 2.0)) / ((pow (sin (SlopeAngleOfWall*pi/180), 2.0) * sin ((SlopeAngleOfWall * AngleOfFrictionSoilAndWall) * pi / 180)) *( 1 + sqrt( ( sin ((AngleOfInternalFriction + AngleOfFrictionSoilAndWall) * pi / 180) * sin ( (AngleOfInternalFriction - BackfillSlope) * pi / 180) / sin ( (SlopeAngleOfWall - AngleOfFrictionSoilAndWall) * pi / 180 ) * sin ( (SlopeAngleOfWall + BackfillSlope) * pi / 180)))));
cout << "The coefficient of active pressure acting on the wall is" << CoefficientOfActivePressure <<"\n"
}
It looks like you are trying to implement Coulomb's Theory of Lateral earth pressure. The formula looks like this:
(From http://www.soilmanagementindia.com)
Assuming that your implementation is correct, the only way to get NaN as result is if the square-root argument is negative.
The bottom line is that the equation is not valid for all possible combinations of input, and for the wrong set of input an output of NaN is to be expected.