Im making a calculator that can code the volume of a sphere, but i cant make the formula without getting the wrong answer. volume of sphere is 4/3 pi r cubed. And cant figure out how to make a fraction without making a complex function. Any idea on how to write out the formula correctly?
}else if (volumeChoice == "sphere"){
double sphereRadius { 0 };
const double pi { 3.14159265358979323846 };
cout << "Enter the radius\n";
cin >> sphereRadius;
double sphereFormula { (4/3) pi * pow(3.0, sphereRadius)};
cout << sphereFormula;
There are a couple main issues I noticed.
One: 4/3 uses integer division in C++, so the result returns 1, not 1.3333...
Change it to 4.0/3.0
Two: There is no multiplication sign between the 4/3 and pi, so it shouldn't compile.
Three: The pow function first parameter is the base, and the second is the exponent. The call should be pow(sphereRadius, 3.0) not pow(3.0, sphereRadius)
The line after changes should look like the following:
double sphereFormula { (4.0/3.0) * pi * pow(sphereRadius, 3.0)};
4 / 3 is integer division (result is 1), and your result will not be accurate because of that. Change it to 4.0 / 3.0 and you should see better results.
I'd be surprised if this code compiles because you're missing a multiplication sign between your four thirds and pi.
Finally, your arguments to pow() are switched. The first argument is the base, the second is the exponent. It never hurts to refer to the documentation.
double sphereFormula{(4.0 / 3.0) * pi * pow(sphereRadius, 3.0)};
A touch more explanation:
C++ reads natural number literals (4 and 3 in your case) as integers. Placing a .0 causes the compiler to read the literal as a double. C++ is not like python or other languages that will produce a decimal result from integer division.
Related
I have a code that tries to solve an integral of a function in a given interval numerically, using the method of Trapezoidal Rule (see the formula in Trapezoid method ), now, for the function sin(x) in the interval [-pi/2.0,pi/2.0], the integral is waited to be zero.
In this case, I take the number of partitions 'n' equal to 4. The problem is that when I have pi with 20 decimal places it is zero, with 14 decimal places it is 8.72e^(-17), then with 11 decimal places, it is zero, with 8 decimal places it is 8.72e^(-17), with 3 decimal places it is zero. I mean, the integral is zero or a number near zero for different approximations of pi, but it doesn't have a clear trend.
I would appreciate your help in understanding why this happens. (I did run it in Dev-C++).
#include <iostream>
#include <math.h>
using namespace std;
#define pi 3.14159265358979323846
//Pi: 3.14159265358979323846
double func(double x){
return sin(x);
}
int main() {
double x0 = -pi/2.0, xf = pi/2.0;
int n = 4;
double delta_x = (xf-x0)/(n*1.0);
double sum = (func(x0)+func(xf))/2.0;
double integral;
for (int k = 1; k<n; k++){
// cout<<"func: "<<func(x0+(k*delta_x))<<" "<<"last sum: "<<sum<<endl;
sum = sum + func(x0+(k*delta_x));
// cout<<"func + last sum= "<<sum<<endl;
}
integral = delta_x*sum;
cout<<"The value for the integral is: "<<integral<<endl;
return 0;
}
OP is integrating y=sin(x) from -a to +a. The various tests use different values of a, all near pi/2.
The approach uses a linear summation of values near -1.0, down to 0 and then up to near 1.0.
This summation is sensitive to calculation error with the last terms as the final math sum is expected to be 0.0. Since the start/end a varies, the error varies.
A more stable result would be had adding the extreme f = sin(f(k)) values first. e.g. sum += sin(f(k=1)), then sum += sin(f(k=3)), then sum += sin(f(k=2)) rather than k=1,2,3. In particular the formation of term x=f(k=3) is likely a bit off from the negative of its x=f(k=1) earlier term, further compounding the issue.
Welcome to the world or numerical analysis.
Problem exists if code used all float or all long double, just different degrees.
Problem is not due to using an inexact value of pi (Exact value is impossible with FP as pi is irrational and all finite FP are rational).
Much is due to the formation of x. Could try the below to form the x symmetrically about 0.0. Compare exactly x generated this way to x the original way.
x = (x0-x1)/2 + ((k - n/2)*delta_x)
Print out the exact values computed for deeper understanding.
printf("x:%a y:%a\n", x0+(k*delta_x), func(x0+(k*delta_x)));
My exercise is to write code which will print the value of this phrase
I have written a code which should work, but when I try to print a value I receive "the value is -nan".
//My Code
#include <iostream>
#include <stdio.h>
#include <cmath>
using namespace std;
int main()
{
double y;
double x = 21;
y = 30 * sqrt(x * (1/(tan(sqrt(3*x) - 2.1))));
printf ("The value is: \n=> %f", y );
}
My question is how can I print the proper value?
try this
printf( "sqrt(3*x) = %lf\n", sqrt(3*x));
printf( "sqrt(3*x) - 2.1 = %lf\n", sqrt(3*x) - 2.1);
printf( "tan(sqrt(3*x) - 2.1) = %lf\n", tan(sqrt(3*x) - 2.1));
then you will notice that the last one is negative which will result in a sqrt of a negative number, thus the NaN
The problem is that, depending on the unit (radians or degrees), you get different results with trigonometric functions. Keep in mind that the tan function expects its argument in radians.
sqrt(3*21)-2.1 = 5.837, and you have to calculate its tangent. It is indeed negative if we work with radians (it is around -0.478), leading to the square root of a negative number which is NaN (Not a Number), but if you use degrees then it is +0.102 and you can complete the calculation. If you want to have the result you would have with degrees, considering the function accepts radians, you must convert the number. The conversion is simple: multiply by Pi and divide by 180. Like this:
y = 30 * sqrt(x * (1/(tan((sqrt(3*x) - 2.1)*M_PI/180))));
In this case the result is 429.967.
If the problem is not related with conversion to radians, i.e. multiplication by M_PI / 180.
In general, operations that produce NaN (Not a Number)1 are:
In your case the result of tan() is negative which leads to negative input value for the outer sqrt(), which is the last example from the above table.
To resolve the problematic situation you could either use some mathematical trick2 and try to rewrite the expression such that it doesn't produce a NaN, or if the problem is in the negative square root, you can use the #include <complex> and:
std::complex<double> two_i = std::sqrt(std::complex<double>(-4));
The rest of the answers provide you with a strategy of how to identify the NaN source, by checking each computation involved
1. Bit patterns reserved for special quantities to handle exceptional situations like taking the square root of a negative number, other than aborting computation are called NaNs.
2. Use trigonometric relations.
where #define M_PI = 3.14159265358979323846;
as i said, i want implement my own double precision cos() function in a compute shader with GLSL, because there is just a built-in version for float.
This is my code:
double faculty[41];//values are calculated at the beginning of main()
double myCOS(double x)
{
double sum,tempExp,sign;
sum = 1.0;
tempExp = 1.0;
sign = -1.0;
for(int i = 1; i <= 30; i++)
{
tempExp *= x;
if(i % 2 == 0){
sum = sum + (sign * (tempExp / faculty[i]));
sign *= -1.0;
}
}
return sum;
}
The result of this code is, that the sum turns out to be NaN on the shader, but on the CPU the algorithm is working well.
I tried to debug this code too and I got the following information:
faculty[i] is positive and not zero for all entries
tempExp is positive in each step
none of the other variables are NaN during each step
the first time sum is NaN is at the step with i=4
and now my question: What exactly can go wrong if each variable is a number and nothing is divided by zero especially when the algorithm works on the CPU?
Let me guess:
First you determined the problem is in the loop, and you use only the following operations: +, *, /.
The rules for generating NaN from these operations are:
The divisions 0/0 and ±∞/±∞
The multiplications 0×±∞ and ±∞×0
The additions ∞ + (−∞), (−∞) + ∞ and equivalent subtractions
You ruled out the possibility for 0/0 and ±∞/±∞ by stating that faculty[] is correctly initialized.
The variable sign is always 1.0 or -1.0 so it cannot generate the NaN through the * operation.
What remains is the + operation if tempExp ever become ±∞.
So probably tempExp is too high on entry of your function and becomes ±∞, this will make sum to be ±∞ too. At the next iteration you will trigger the NaN generating operation through: ∞ + (−∞). This is because you multiply one side of the addition by sign and sign switches between positive and negative at each iteration.
You're trying to approximate cos(x) around 0.0. So you should use the properties of the cos() function to reduce your input value to a value near 0.0. Ideally in the range [0, pi/4]. For instance, remove multiples of 2*pi, and get the values of cos() in [pi/4, pi/2] by computing sin(x) around 0.0 and so on.
What can go dramatically wrong is a loss of precision. cos(x) usually is implemented by range reduction followed by a dedicated implementation for the range [0, pi/2]. Range reduction uses cos(x+2*pi) = cos(x). But this range reduction isn't perfect. For starters, pi cannot be exactly represented in finite math.
Now what happens if you try something as absurd as cos(1<<30) ? It's quite possible that the range reduction algorithm introduces an error in x that's larger than 2*pi, in which case the outcome is meaningless. Returning NaN in such cases is reasonable.
I understand why floating point numbers can't be compared, and know about the mantissa and exponent binary representation, but I'm no expert and today I came across something I don't get:
Namely lets say you have something like:
float denominator, numerator, resultone, resulttwo;
resultone = numerator / denominator;
float buff = 1 / denominator;
resulttwo = numerator * buff;
To my knowledge different flops can yield different results and this is not unusual. But in some edge cases these two results seem to be vastly different. To be more specific in my GLSL code calculating the Beckmann facet slope distribution for the Cook-Torrance lighitng model:
float a = 1 / (facetSlopeRMS * facetSlopeRMS * pow(clampedCosHalfNormal, 4));
float b = clampedCosHalfNormal * clampedCosHalfNormal - 1.0;
float c = facetSlopeRMS * facetSlopeRMS * clampedCosHalfNormal * clampedCosHalfNormal;
facetSlopeDistribution = a * exp(b/c);
yields very very different results to
float a = (facetSlopeRMS * facetSlopeRMS * pow(clampedCosHalfNormal, 4));
facetDlopeDistribution = exp(b/c) / a;
Why does it? The second form of the expression is problematic.
If I say try to add the second form of the expression to a color I get blacks, even though the expression should always evaluate to a positive number. Am I getting an infinity? A NaN? if so why?
I didn't go through your mathematics in detail, but you must be aware that small errors get pumped up easily by all these powers and exponentials. You should try and substitute all variables var with var + e(var) (on paper, yes) and derive an expression for the total error - without simplifying in between steps, because that's where the error comes from!
This is also a very common problem in computational fluid dynamics, where you can observe things like 'numeric diffusion' if your grid isn't properly aligned with the simulated flow.
So get a clear grip on where the biggest errors come from, and rewrite equations where possible to minimize the numeric error.
edit: to clarify, an example
Say you have some variable x and an expression y=exp(x). The error in x is denoted e(x) and is small compared to x (say e(x)/x < 0.0001, but note that this depends on the type you are using). Then you could say that
e(y) = y(x+e(x)) - y(x)
e(y) ~ dy/dx * e(x) (for small e(x))
e(y) = exp(x) * e(x)
So there's a magnification of the absolute error of exp(x), meaning that around x=0 there's really no issue (not a surprise, since at that point the slope of exp(x) equals that of x) , but for big x you will notice this.
The relative error would then be
e(y)/y = e(y)/exp(x) = e(x)
whilst the relative error in x was
e(x)/x
so you added a factor of x to the relative error.
This is probably an easy one, but is the right way to calculate volume for a sphere in C++? My getArea() seems to be right, but when I call getVolume() it doesn't output the right amount. With a sphere of radius = 1, it gives me the answer of pi, which is incorrect:
double Sphere::getArea() const
{
return 4 * Shape::pi * pow(getZ(), 2);
}
double Sphere::getVolume() const
{
return (4 / 3) * Shape::pi * pow(getZ(), 3);
}
You're using integer division in (4 / 3). Instead, use floating point division: (4.0 / 3.0).
4/3 is 1, because integer division only produces integers. You can confirm this by test code: std::cout << (4/3) << std::endl;.
In (4 / 3), these are both integers so you get integer division. That means the result will be truncated (1.333... becomes 1). Make one of them a double so the other gets promoted to a double during division, yielding a correct result.
I prefer to use (4.0 / 3.0).
(4 / 3) is an integer expression and is therefore being truncated to 1. Try (4.0 / 3.0)