Best platform independent pi constant? - c++

I know that you can use:
#define _USE_MATH_DEFINES
and then:
M_PI
to get the constant pi. However, if I remember correctly (comments welcome) this is compiler/platform dependent. So, what would be the most reliable way to use a pi constant that won't cause any problems when I port it from Linux to other systems?
I know that I could just define a float/double and then set it to a rounded pi value myself, but I'd really like to know if there is a designated mechanism.

Meeting C++ has an article on the different options for generating pi: C++ & π they discuss some of the options, from cmath, which is not platform independent:
double pi = M_PI;
std::cout << pi << std::endl;
and from boost:
std::cout << boost::math::constants::pi<double>() << std::endl
and using atan, with constexpr removed since as SchighSchagh points out that is not platform independent:
double const_pi() { return std::atan(1)*4; }
I gathered all the methods into a live example:
#include <iostream>
#include <cmath>
#include <boost/math/constants/constants.hpp>
double piFunc() { return std::atan(1)*4; }
int main()
{
double pi = M_PI;
std::cout << pi << std::endl;
std::cout << boost::math::constants::pi<double>() << std::endl ;
std::cout << piFunc() << std::endl;
}
C++2a pi_v
In C++2a we should get pi_v:
#include <numbers>
#include <iostream>
int main() {
std::cout<< std::numbers::pi_v<double> <<"\n";
}

The function below calculates pi without relying on any libraries at all.
Also, the type of its result is a template parameter.
Platform ueber-independence is stifled a bit because it only works with fixed-precision fractional types -- the calculated value needs to converge and remain constant over 2 iterations.
So if you specify some kind of arbitrary-precision rational or floating-point class which will automatically increase its precision as needed, a call to this function will not end well.
#include <iostream>
#include <iomanip>
namespace golf {
template <typename T> inline T calc_pi() {
T sum=T(0), k8=T(0), fac=T(1);
for(;;) {
const T next =
sum + fac*(T(4)/(k8+T(1))-T(2)/(k8+T(4))-T(1)/(k8+T(5))-T(1)/(k8+T(6)));
if(sum == next) return sum;
sum=next;
fac /= T(16);
k8 += T(8);
} }
static const auto PI = calc_pi<double>();
}
int main() {
std::cout << std::setprecision(16) << golf::PI << std::endl;
return 0;
}

Related

How ceil function works in c++?

When I execute this code the value of ans1, ans2 is 50002896 and 50005000.
I know there is some issues with ceil function but was not able to figure out the exact cause.
#include <bits/stdc++.h>
using namespace std;
int main()
{
long long ans1 = 0, ans2 = 0;
for (long long i = 1; i <= 10000; i++)
{
ans1 = ans1 + ceil((float)i / 1);
ans2 = ans2 + i;
}
cout << ans1 << " " << ans2 << endl;
}
The source of the problem is not the ceil function, but rather that not all integers can be represented accuratly as floating point values.
Some more info about floating point representation: Wikipedia IEEE 754. And a related post: Which is the first integer that an IEEE 754 float is incapable of representing exactly?.
The following code is a minimal demonstration of the same issue that causes your issue:
float f1 = 100000000;
f1++;
std::cout << std::to_string(f1) << std::endl;
[Wrong] Output (expected: +1):
100000000.000000
One approach would be to use double instead of float.
This will not solve the principle issue, but will make the range of representable integers a lot bigger:
double f1 = 100000000;
f1++;
std::cout << std::to_string(f1) << std::endl;
Output:
100000001.000000
Some side notes:
better to avoid #include <bits/stdc++.h> - see here: Why should I not #include <bits/stdc++.h>?.
better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
First, try to use specific headers like #include , in this case, .because #include <bits/stdc++.h> will bring lots of junk.
So the issue is with float not ceil explained below
floating-point values do not represent exact values.
Code:-
#include <iostream>
#include <iomanip>
using namespace std;
// Driver Code
int main()
{
float num1 = 10000.29;
float num2 = 10000.2;
// Output should be 0.0900000000
cout << std::setprecision(15)
<< (num1 - num2);
return 0;
}
Output :-
0.08984375

How do you use setprecision() when declaring a double variable in C++?

So I'm trying to learn more about C++ and I'm practicing by making a calculator class for the quadratic equation. This is the code for it down below.
#include "QuadraticEq.h"
string QuadraticEq::CalculateQuadEq(double a, double b, double c)
{
double sqrtVar = sqrt(pow(b, 2) - (4 * a * c));
double eqPlus = (-b + sqrtVar)/(2 * a);
double eqMinus = (-b - sqrtVar) / (2 * a);
return "Your answers are " + to_string(eqPlus) + " and " + to_string(eqMinus);
}
I'm trying to make it so that the double variables eqPlus and eqMinus have only two decimal points. I've seen people say to use setprecision() but I've only seen people use that function in cout statements and there are none in the class because I'm not printing a string out I'm returning one. So what would I do here? I remember way before learning about some setiosflags() method, is there anything I can do with that?
You can use stringstream instead of the usual std::cout with setprecision().
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
std::string adjustDP(double value, int decimalPlaces) {
// change the number of decimal places in a number
std::stringstream result;
result << std::setprecision(decimalPlaces) << std::fixed << value;
return result.str();
}
int main() {
std::cout << adjustDP(2.25, 1) << std::endl; //2.2
std::cout << adjustDP(0.75, 1) << std::endl; //0.8
std::cout << adjustDP(2.25213, 2) << std::endl; //2.25
std::cout << adjustDP(2.25, 0) << std::endl; //2
}
However, as seen from the output, this approach introduces some rounding off errors when value cannot be represented exactly as a floating point binary number.

I included StlLock.h in my .h file and got these errors

Ok, so I just installed Visual Studio yesterday and was just minding my own business trying to make a learn C++/wasting time. I ran the code you're about to see a few times without issue and then I included the StlLock.h file, then I happened upon this error list.
Error list in my Visual Studio along with the "problematic" code, I guess.
The errors vanish as soon as I remove StlLock.h.
As far as I recall I did not touch StlLock.h at all. Is there just something wrong with it?
Also, I'm pretty new to programming and C++. I'm trying to teach myself but got caught up in this.
The full code is in 2 files:
ABLASAN.cpp
#include "ABLASAN.h"
int main()
{
Math test;
test.Show_Atributes();
test.radijus = 4;
std::cout << test.Area(test.radijus) << "\n";
std::cin.get();
}
ABLASAN.h
#pragma once
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <StlLock.h>
#include <cmath>
constexpr double PI = 3.14159265358979323846;
class Math{
public:
double radijus, x_os, y_os;
Math(){
x_os = 0;
y_os = 0;
radijus = 0;
}
double Area(double x, double y)
{
return x * y;
}
double Area(double r)
{
return pow(r, 2) * PI;
}
void Show_Atributes() {
std::cout << "X-os: " << x_os << "\nY-os: " << y_os << "\nRadijus: " << radijus << std::endl;
}
};
P.S.
Just as a side-note: I used the cmath file and read somewhere that that file has defined mathematical constants using this:
#define _USE_MATH_DEFINES
#include <cmath>
#include <iostream>
int main() {
std::cout << M_PI << " " << M_E << " " << M_SQRT2 << endl;
return 0;
}
I can't seem to get that to work.
I'm using the Visual Studio C++20 compiler just in case it's important. Also, I did not change any project settings/properties/anything.
Thanks to everyone and anyone in advance.
Also, I'm deeply sorry if this was already answered somewhere. I just didn't find it before writing this up.

Boost Polygon: Issue with euclidean_distance

I have the following code which is supposed to compute the Euclidean distance between two rectangles. I compiled using GCC 4.7.3 and Boost v1.58.0
#include <iostream>
#include <cmath>
#include <boost/polygon/polygon.hpp>
#include <boost/geometry.hpp>
namespace gtl = boost::polygon;
using namespace boost::polygon::operators;
typedef gtl::rectangle_data<int> LayoutRectangle;
int main(int argc, char** argv)
{
LayoutRectangle t(16740130,29759232,16740350,29760652);
LayoutRectangle n(16808130,29980632,16808350,29982052);
std::cout << gtl::euclidean_distance(t, n) << std::endl;
std::cout << gtl::euclidean_distance(t, n, gtl::HORIZONTAL) << " "
<< gtl::euclidean_distance(t, n, gtl::VERTICAL) << std::endl;
std::cout << gtl::square_euclidean_distance(t, n) << std::endl;
std::cout << std::sqrt(gtl::square_euclidean_distance(t, n)) << std::endl;
std::cout << (int) std::sqrt(gtl::square_euclidean_distance(t, n)) << std::endl;
return 0;
}
The code above produced the following output:
38022.6
67780 219980
52985328800
230185
230185
The correct answer is 230185. Now if I go look at the implementation of euclidean_distance() in the boost polygon library, I see this:
template <typename rectangle_type, typename rectangle_type_2>
typename enable_if< typename gtl_and_3<y_r_edist2, typename is_rectangle_concept<typename geometry_concept<rectangle_type>::type>::type,
typename is_rectangle_concept<typename geometry_concept<rectangle_type_2>::type>::type>::type,
typename rectangle_distance_type<rectangle_type>::type>::type
euclidean_distance(const rectangle_type& lvalue, const rectangle_type_2& rvalue) {
double val = (int)square_euclidean_distance(lvalue, rvalue);
return std::sqrt(val);
}
This looks identical to the std::sqrt(gtl::square_eclidean_distance(t,n)) line in my code which gives the correct answer (230185). So why am I getting 38022.6 with gtl::euclidean_distance()? What am I not seeing here?
Looks like the internal computation is overflowing.
I don't think this is a library bug, the library is used incorrectly with the underlying (unchecked) int type.
(However, there is a different bug in the library that I mention at the end.)
Try using a smaller "integer representation" of the problem:
For example:
LayoutRectangle t(167402,297592,167404,297607);
LayoutRectangle n(168082,299806,168084,299821);
Unfortunately there is no general solution of the problem in integer arithmetic, except 0) using higher precision can buy you something, 1) scaling the problem 2) using multiprecision, 3) using rational arithmetic and integer part
(For floating point the solution is simply normalizing the components, this is how std::abs for std::complex<double> works to avoid floating point overflow)
It is good to use large integers to represent a geometric problem BUT
for this reason, as a workaround, use coordinates that span distance of at most (int)std::sqrt((double)std::numeric_limits<int>::max()/2) = 2^15 = 32768.
Which is a surprisingly small number.
Complete code:
#include <iostream>
#include <cmath>
#include <boost/polygon/polygon.hpp>
#include <boost/geometry.hpp>
int main(){
namespace gtl = boost::polygon;
using namespace boost::polygon::operators;
typedef gtl::rectangle_data<int> LayoutRectangle;
LayoutRectangle t(167401,297592,167403,297606);
LayoutRectangle n(168081,299806,168083,299820);
std::cout << gtl::euclidean_distance(t, n) << std::endl;
std::cout << gtl::euclidean_distance(t, n, gtl::HORIZONTAL) << " "
<< gtl::euclidean_distance(t, n, gtl::VERTICAL) << std::endl;
std::cout << gtl::square_euclidean_distance(t, n) << std::endl;
std::cout << std::sqrt(gtl::square_euclidean_distance(t, n)) << std::endl;
std::cout << (int) std::sqrt(gtl::square_euclidean_distance(t, n)) << std::endl;
}
Output:
2302.1
678 2200
5299684
2302.1
2302
Which is the expected result.
Looking at the code, it seems that there is a bug in the library, not because it gives overflow but because an internal computation is casted to int and not the the underlying generic integer data type. This means that probably even if you use multiprecision integers the results will overflow.

How to get a number closest to the average in c++?

What I'm trying to achieve is to take the average of the numbers stored in the array and find the number which is closest to it.
My code compiles, but has an error just after starting. I think it's something to do with the memory handling (I don't feel confident with pointers, etc. yet)
Could some nice guy take a look at my code and tell me what's wrong with it? (don't be hard on me, I'm a beginner)
#include <iostream>
#include <cmath>
using namespace std;
double* aver(double* arr, size_t size, double& average);
int main()
{
double arr[] = {1,2,3,4,5,7};
size_t size = sizeof(arr)/sizeof(arr[0]);
double average = 0;
double* p = aver(arr,size,average);
cout << *p << " " << average << endl;
}
double* aver(double* arr, size_t size, double& average){
int i,j,sum;
double* m = 0;
int tmp[7];
for(i=0;i<size;i++)
sum += arr[i];
average = sum/size;
for(j=0;j<size;j++){
tmp[j] = arr[j] - average;
if(abs(tmp[j])>*m)
*m = tmp[j];
}
return m;
}
The following
double* m = 0;
sets m to the null pointer. Any attempt to dereference it will result in undefined behaviour.
Change the above to:
double m = 0;
and replace *m with m everywhere, also changing the function's return type to just double.
Finally, you don't need the tmp array.
1 What's wrong with your code? The use of pointers and the resulting beginner errors.
2 How to compute the average in C++? Roughly like this:
#include <iostream>
#include <iomanip>
#include <vector>
#include <numeric>
int main()
{
std::vector<double> arr = {1,2,3,4,5,7};
auto average = std::accumulate(std::begin(arr),std::end(arr),0.0) / arr.size();
std::cout << " average = " << std::setprecision(16) << average << std::endl;
}
(note: compile with option -std=c++11)
3 How to find the number closest to it (the average)? If your computer is IEEE compliant (most are but some compiler optimisations violate that), the result of any arithmetic is rounded to the closest representable number. So, nothing special needs to be done here. However, accumulation of numbers is subject to round-off error and hence loss of precision. This can be minimised by accumulating the numbers in descending order of their absolute value, though there exist pathological cases where the computed accumulation is still rather imprecise. Find out more on, say, wikipedia.
4 How to find the array value closest to it (the average)? One way is shown in Johan's answer. However, it unnecessarily alters the array by performing a partial sort. Better use std::min_element
(no need to std::transform):
auto comp = [average](double left, double right)
{ return std::abs(left-average) < std::abs(right-average); };
auto closest = std::min_element(std::begin(arr), std::end(arr), comp);
std::cout << " value closest to average was "
<< *closest << " at position "
<< (closest-std::begin(arr))
<< std::endl;
building on to the answer by Walter, adding the 'find value closest to average' part:
#include <iostream>
#include <vector>
#include <numeric>
#include <cmath>
#include <algorithm>
int main()
{
std::vector<double> arr = {1,2,3,4,5,7};
auto average = std::accumulate(std::begin(arr),std::end(arr),0.0) / arr.size();
std::cout << " average = " << average << std::endl;
auto comp = [average](double left,double right){
return std::abs(left-average)<std::abs(right-average); };
auto mini=std::min_element(std::begin(arr),std::end(arr),comp);
std::cout << "value closest to average was " << *mini <<std::endl;
}
Alternative (slower) implementation using transform (reduces the number of calls to fabs, but does a copy):
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
int main()
{
std::vector<double> arr = {1,2,3,4,5,7};
auto average = std::accumulate(std::begin(arr),std::end(arr),0.0) / arr.size();
std::cout << " average = " << average << std::endl;
auto pred=[average](double x){return std::abs(x-average);};
auto arrcpy = arr;
std::transform(std::begin(arr),std::end(arr),std::begin(arrcpy),pred);
auto result = std::min_element(std::begin(arrcpy),std::end(arrcpy));
std::cout << "value closest to average was: " << arr[result-std::begin(arrcpy)];
}
Using a standard algorithm is usually the right thing to do as it is more maintainable. In this case I did not find a way to use a standard algorithm as fast as this (about 30% faster than the first solution above with 10e7 elements and -O2):
std::pair<double,double> smallest(std::abs(average-arr[0]),arr[0]);
for(auto a: arr){
auto v=std::abs(average-a);
if(v<smallest.first){
smallest={v,a};
}
}
std::cout << "value closest to average was " << smallest.second <<std::endl;