When I use the atan function from cmath and math on a floating point number, I seem to get different answers:
#include <cmath>
#include <math.h>
#include <iostream>
#include <iomanip>
int main() {
std::cout << std::setprecision(20) << atan(-0.57468467f) << std::endl;
std::cout << std::setprecision(20) << std::atan(-0.57468467f) << std::endl;
// I get:
// -0.52159727580733605823
// -0.52159726619720458984
}
Why does this happen? Does two libraries implement atan differently?
math.h's atan takes a double and returns a double, yet cmath's is overloaded so that a float argument (as used here) will be used as a float and yield a float result. Thus, the difference in output comes from using two different floating-point types. To make them use the same type, either remove the f at the ends of the numbers or change the first atan to atanf.
Related
The following code
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>, boost::multiprecision::et_off> float_50;
int main()
{
float_50 a = boost::multiprecision::pow((float_50)5, (float_50)10); // works
double b = boost::multiprecision::pow((double)5, (double)10); // doesn't work
//double b = boost::multiprecision::pow<double>((double)5, (double)10); // Why can't be overloaded?
return 0;
}
won't compile since boost::multiprecision::pow does not recognised fixed precision type. What is the usual solution for this? I'd rather have a single pow function which accepts both multi and fixed precision types. It is strange to me that boost constants, for instance, have template definitions so
boost::math::constants::pi<double>()
boost::math::constants::pi<float_50>()
work fine. Shouldn't boost::multiprecision::pow also be overloaded?
The solution is to leave off the namespace.
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/cpp_int.hpp>
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>, boost::multiprecision::et_off> float_50;
int main()
{
float_50 a = pow((float_50)5, (float_50)10);
double b = pow(5., 10.);
return 0;
}
There is no way for a single function to handle arguments of different types. You need a separate function for each supported parameter set. The function may be autogenerated from a template—but pow does not seem to be a candidate for a template implementation.
I have been trying to find a library/function that computes the Bessel function of the first kind, but with non-integer values.
I have the following program.
// Include standard libraries
#include <cstdlib>
#include <cmath>
#include <vector>
#include <array>
#include <iostream>
int main(int nargs, char* args[])
{
std::cout << "bessel function " << jn(5./2., 1.) << "\n" ;
}
However, it seems this function only calculates for integer values, so in the example I get the first Bessel function for n=2.
Anyone knows how I can determine the first Bessel function with non-integer values?
EDIT: I want to find a function in C++ that calculate J_(5/2)(x) for me.
boost library could be an answer. The Bessel function of the first kind is called cyl_bessel_j(v, x). Second kind cyl_neumann(v, x). Both works for real v.
Interesting alteranative here is the ROOT library from CERN with a lot of functions for scientific computation.
Consider the following code which creates a multiprecision floating-point number 'a' by using boost.
How do I use boost library to invoke trigonometric functions?
For example, I hope to calculate sin(a).
#include <iostream>
#include "boost/multiprecision/cpp_bin_float.hpp"
using namespace std;
using namespace boost::multiprecision;
typedef number<backends::cpp_bin_float<24, backends::digit_base_2, void, boost::int16_t, -126, 127>, et_off> float32;
int main (void) {
float32 a("0.5");
return 0;
}
It looks like there is a limitation in the library. When the precision is dropped too low, the sin implementation no longer compiles.
Some intermediate calculations are being done in double precision. The assignment into the result type would be lossy and hence doesn't compile.
Your chosen type actually corresponds to cpp_bin_float_single. That doesn't compile.
As soon as you select cpp_bin_float_double (precision 53 binary digits) or higher, you'll be fine.
I suppose this limitation could be viewed as a bug in some respects. You might report it to the library devs, who will be able to judge whether the related code could use single-precision floats there without hurting the convergence of the sin approximation.
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <iostream>
using namespace std;
using namespace boost::multiprecision;
int main() {
cpp_bin_float_100 a = 1;
cout << setprecision(50) << endl;
cout << sin(a) << endl;
return 0;
}
I've verified digits with Wolfram Mathematica and they are correct:
I'm trying to understand the strange behavior of the following program. Obviously, an overflow occurs during the definition of the global variable "bug", but the program throws a floating point exception during the innocent calculation 1.0+2.0.
#include <iostream>
#include <cmath>
#include <fenv.h>
using namespace std;
const double bug = pow(10.0,pow(10.0,10.0));
int main(void)
{
feenableexcept(-1);
cout << "before" << endl;
cout << 1.0 + 2.0 << endl;
cout << "after" << endl;
return 0;
}
I tried compiling it with both g++ and clang++, but got the same output in both
before
Floating point exception
const double bug = pow(10.0,pow(10.0,10.0)); should be used. Because pow need (double,double) argument and you are passing (int,int)
Once I encountered similar case when floating point error manifested itself at strange places. As I understood this happened because FPU status register is syncronized not during every floating point instruction so error may appear to be random. By the way, I've just compiled and started your program and it finished without any issues.
My solution was to clear FPU status register after faulty calculation (of course this is hack but at that time I couldn't analize that math library).
Right now I have this little code that I want to print pi to x decimals:
#include <iostream>
#include <gmpxx.h>
#include <math.h>
using namespace std;
int main()
{
mpf_set_default_prec(1000);
mpf_t pi;
mpf_init(pi);
mpf_set_d(pi, atan(1)*4);
cout << pi << endl;
}
I just sat default_prec to 1000 as I thought that would give me plenty of decimals, but no matter what I set it to, I only get 5. How can I print more?
The problem is atan(1)*4 will only be evaluated with single (or double) precision, since this part of the code has nothing to do with gmp and will use the standard c++ types. The program will evaluate atan(1)*4 first and then convert the result into an mpf_t.
On the GMP homepage there is a page on how to calculate Pi with many digits.