I am writing a project in Visual Studio then I use GCC in order to compile it. Sometimes it causes some problems: This time I cannot use sqrtf function because VS accepts it however GCC does not. So I need to find some way (maybe mathematical approach to calculate square root) to find square root of some number in a way both GCC and VS will accept. To be more precise this is the line which causes a problem:
float x_f = circleRadius - sqrtf((float)((circleRadius * circleRadius) - (y * y)));
I need to find the square root of (circleRadius^2 - y^2)
std::sqrt solves this problem:
#include <cmath>
auto foo(int circleRadius, int y) {
float x_f = circleRadius - std::sqrt((float)(circleRadius * circleRadius - y * y));
}
compiles for both msvc and gcc according to https://godbolt.org/z/g9MJH6
You should prefer std::sqrt to sqrtf in C++. It works with more types, i.e., you could write your function more generically. It also does not use hungarian notation.
Edit: If you do not care if the calculation returns a float or a double, you could omit the cast and write the following:
auto x_f = circleRadius - std::sqrt(circleRadius * circleRadius - y * y);
If you care that a float is used, you can use std::sqrtf instead.
If you have to use a cast, you should generally prefer static_cast to C-style casts. Reasons for this are listed here.
Your situation may be if you use newer compiler at VC and older compiler at gcc.
Try to use sqrt or sqrtf WITH
#include <math.h>
Don't use
#include <cmath>
math.h should have sqrt, sqrtf definitions for both compilers.
Related
Consider the following piece of code:
#include <iostream>
#include <cmath>
int main() {
int i = 23;
int j = 1;
int base = 10;
int k = 2;
i += j * pow(base, k);
std::cout << i << std::endl;
}
It outputs "122" instead of "123". Is it a bug in g++ 4.7.2 (MinGW, Windows XP)?
std::pow() works with floating point numbers, which do not have infinite precision, and probably the implementation of the Standard Library you are using implements pow() in a (poor) way that makes this lack of infinite precision become relevant.
However, you could easily define your own version that works with integers. In C++11, you can even make it constexpr (so that the result could be computed at compile-time when possible):
constexpr int int_pow(int b, int e)
{
return (e == 0) ? 1 : b * int_pow(b, e - 1);
}
Here is a live example.
Tail-recursive form (credits to Dan Nissenbaum):
constexpr int int_pow(int b, int e, int res = 1)
{
return (e == 0) ? res : int_pow(b, e - 1, b * res);
}
All the other answers so far miss or dance around the one and only problem in the question:
The pow in your C++ implementation is poor quality. It returns an inaccurate answer when there is no need to.
Get a better C++ implementation, or at least replace the math functions in it. The one pointed to by Pascal Cuoq is good.
Not with mine at least:
$ g++ --version | head -1
g++ (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2)
$ ./a.out
123
IDEone is also running version 4.7.2 and gives 123.
Signatures of pow() from http://www.cplusplus.com/reference/cmath/pow/
double pow ( double base, double exponent );
long double pow ( long double base, long double exponent );
float pow ( float base, float exponent );
double pow ( double base, int exponent );
long double pow ( long double base, int exponent );
You should set double base = 10.0; and double i = 23.0.
If you simply write
#include <iostream>
#include <cmath>
int main() {
int i = 23;
int j = 1;
int base = 10;
int k = 2;
i += j * pow(base, k);
std::cout << i << std::endl;
}
what do you think is pow supposed to refer to? The C++ standard does not even guarantee that after including cmath you'll have a pow function at global scope.
Keep in mind that all the overloads are at least in the std namespace. There is are pow functions that take an integer exponent and there are pow functions that take floating point exponents. It is quite possible that your C++ implementation only declares the C pow function at global scope. This function takes a floating point exponent. The thing is that this function is likely to have a couple of approximation and rounding errors. For example, one possible way of implementing that function is:
double pow(double base, double power)
{
return exp(log(base)*power);
}
It's quite possible that pow(10.0,2.0) yields something like 99.99999999992543453265 due to rounding and approximation errors. Combined with the fact that floating point to integer conversion yields the number before the decimal point this explains your result of 122 because 99+3=122.
Try using an overload of pow which takes an integer exponent and/or do some proper rounding from float to int. The overload taking an integer exponent might give you the exact result for 10 to the 2nd power.
Edit:
As you pointed out, trying to use the std::pow(double,int) overload also seems to yield a value slightly less 100. I took the time to check the ISO standards and the libstdc++ implementation to see that starting with C++11 the overloads taking integer exponents have been dropped as a result of resolving defect report 550. Enabling C++0x/C++11 support actually removes the overloads in the libstdc++ implementation which could explain why you did not see any improvement.
Anyhow, it is probably a bad idea to rely on the accuracy of such a function especially if a conversion to integer is involved. A slight error towards zero will obviously make a big difference if you expect a floating point value that is an integer (like 100) and then convert it to an int-type value. So my suggestion would be write your own pow function that takes all integers or take special care with respect to the double->int conversion using your own round function so that a slight error torwards zero does not change the result.
Your problem is not a bug in gcc, that's absolutely certain. It may be a bug in the implementation of pow, but I think your problem is really simply the fact that you are using pow which gives an imprecise floating point result (because it is implemented as something like exp(power * log(base)); and log(base) is never going to be absolutely accurate [unless base is a power of e].
Consider the following piece of code:
#include <iostream>
#include <cmath>
int main() {
int i = 23;
int j = 1;
int base = 10;
int k = 2;
i += j * pow(base, k);
std::cout << i << std::endl;
}
It outputs "122" instead of "123". Is it a bug in g++ 4.7.2 (MinGW, Windows XP)?
std::pow() works with floating point numbers, which do not have infinite precision, and probably the implementation of the Standard Library you are using implements pow() in a (poor) way that makes this lack of infinite precision become relevant.
However, you could easily define your own version that works with integers. In C++11, you can even make it constexpr (so that the result could be computed at compile-time when possible):
constexpr int int_pow(int b, int e)
{
return (e == 0) ? 1 : b * int_pow(b, e - 1);
}
Here is a live example.
Tail-recursive form (credits to Dan Nissenbaum):
constexpr int int_pow(int b, int e, int res = 1)
{
return (e == 0) ? res : int_pow(b, e - 1, b * res);
}
All the other answers so far miss or dance around the one and only problem in the question:
The pow in your C++ implementation is poor quality. It returns an inaccurate answer when there is no need to.
Get a better C++ implementation, or at least replace the math functions in it. The one pointed to by Pascal Cuoq is good.
Not with mine at least:
$ g++ --version | head -1
g++ (GCC) 4.7.2 20120921 (Red Hat 4.7.2-2)
$ ./a.out
123
IDEone is also running version 4.7.2 and gives 123.
Signatures of pow() from http://www.cplusplus.com/reference/cmath/pow/
double pow ( double base, double exponent );
long double pow ( long double base, long double exponent );
float pow ( float base, float exponent );
double pow ( double base, int exponent );
long double pow ( long double base, int exponent );
You should set double base = 10.0; and double i = 23.0.
If you simply write
#include <iostream>
#include <cmath>
int main() {
int i = 23;
int j = 1;
int base = 10;
int k = 2;
i += j * pow(base, k);
std::cout << i << std::endl;
}
what do you think is pow supposed to refer to? The C++ standard does not even guarantee that after including cmath you'll have a pow function at global scope.
Keep in mind that all the overloads are at least in the std namespace. There is are pow functions that take an integer exponent and there are pow functions that take floating point exponents. It is quite possible that your C++ implementation only declares the C pow function at global scope. This function takes a floating point exponent. The thing is that this function is likely to have a couple of approximation and rounding errors. For example, one possible way of implementing that function is:
double pow(double base, double power)
{
return exp(log(base)*power);
}
It's quite possible that pow(10.0,2.0) yields something like 99.99999999992543453265 due to rounding and approximation errors. Combined with the fact that floating point to integer conversion yields the number before the decimal point this explains your result of 122 because 99+3=122.
Try using an overload of pow which takes an integer exponent and/or do some proper rounding from float to int. The overload taking an integer exponent might give you the exact result for 10 to the 2nd power.
Edit:
As you pointed out, trying to use the std::pow(double,int) overload also seems to yield a value slightly less 100. I took the time to check the ISO standards and the libstdc++ implementation to see that starting with C++11 the overloads taking integer exponents have been dropped as a result of resolving defect report 550. Enabling C++0x/C++11 support actually removes the overloads in the libstdc++ implementation which could explain why you did not see any improvement.
Anyhow, it is probably a bad idea to rely on the accuracy of such a function especially if a conversion to integer is involved. A slight error towards zero will obviously make a big difference if you expect a floating point value that is an integer (like 100) and then convert it to an int-type value. So my suggestion would be write your own pow function that takes all integers or take special care with respect to the double->int conversion using your own round function so that a slight error torwards zero does not change the result.
Your problem is not a bug in gcc, that's absolutely certain. It may be a bug in the implementation of pow, but I think your problem is really simply the fact that you are using pow which gives an imprecise floating point result (because it is implemented as something like exp(power * log(base)); and log(base) is never going to be absolutely accurate [unless base is a power of e].
I want to use exponential function which returns IEEE_FLOAT64 value
Currently I am using expf function, but still I am getting lots of warnings.
value = IEEEPosOne - (IEEE_FLOAT64)expf(value1);
From man 3 exp:
NAME
exp, expf, expl - base-e exponential function
SYNOPSIS
#include <math.h>
double exp(double x);
float expf(float x);
long double expl(long double x);
Link with -lm.
So just use exp().
//c++
#include <cmath>
double x = 7.0;//float64
auto y = std::exp(x);//exp(float64);
C++ standard provides appropriate overloads. No need to reflect operand type in function name.
This does answer does not apply to C only for C++
For C see #iBug's answer.
The C++ standard does not require an implementation to use the IEEE standard. Though this is usually the easiest floating point implementation to use as the chips are relatively standard in modern machines.
The standard provides a way to check using std::numeric_limits.
So if it is a requirement then you should validate.
#include <limits>
#include <iostream>
int main()
{
static_assert(sizeof(double) == 64);
static_assert(std::numeric_limits<double>::is_iec559());
// If the above compiles your double is IEEE 64 bit value.
// Or IEEE_754 compliant https://en.wikipedia.org/wiki/IEEE_754_revision
}
Now that you have established you are using IEEE values you can look at the cmath header to see that the functions there all take and return a double value.
exp
log
etc....
Note: You should note that Windows machines (usually) use an 80 bit floating point register (not 64). So things can get super whaky if you need strict compliance.
Note: Do NOT use:
expf() for float,
expl() for long double
These are for C library users where the language does not do the correct type checking. In C++ the language uses overloading to use the correct version of the function. If you look at the standard for exp:
Defined in header <cmath>
* float exp( float arg );
* double exp( double arg );
* long double exp( long double arg );
* double exp( Integral arg );
The above are all in the standard namespace.
std::cout << std::exp(100000.1) << "\n";
Notice that exp() can take any floating point type float, double or long double and generate the appropriate result type.
I am receiving an error because of the following code :
const double angle = deg2rad(180);
The error says:
Function 'deg2rad' could not be resolved
I have recently installed 'Eclipse IDE for C/C++ Developers' and I have added -std=c++11 to Other flags at C/C++ Build/Settings/Tool Settings/GCC C++ Compiler/Miscellaneous
Any ideas what might be wrong?
The C++ standard library does not include a deg2rad function. You will need to create your own, or include a library which has one. An example of such a function is:
#include <cmath>
double deg2rad(double deg) {
return deg * M_PI / 180.0;
}
Note that M_PI is not actually part of the standard either, but is commonly included in the cmath header. If you are using Visual C++ you will need to define _USE_MATH_DEFINES to enable it.
There is no deg2rad() in the C++11 standard so, unless it's provided by some other library, you'll have to write your own. Something like this should do as a start:
double deg2rad (double degrees) {
return degrees * 4.0 * atan (1.0) / 180.0;
}
As per the above code, I normally leave micro-optimisations up to the compiler, such as letting it decide whether short functions should be inlined, or whether it will constant-fold the expression 4.0 * atan (1.0) / 180.0 into a single constant.
However, there may be a case in certain circumstances (such as if the compiler isn't as clever as the ones I use) to explicitly add the optimisations (keeping in mind that inline is a suggestion to the compiler rather than a demand):
inline double deg2rad (double degrees) {
static const double pi_on_180 = 4.0 * atan (1.0) / 180.0;
return degrees * pi_on_180;
}
C++ does not implement a deg2rad function, so you will need to write it by yourself.
inline double deg2rad(double deg)
{
return deg * M_PI / 180.;
}
Notice how we declare the function inline: This is because we don't want to waste extra assembly instructions setting up the call stack and jumping to the address of the function. When the function is inlined, it is substituted into the place it was called from. Note that inline is just advice to the compiler, and it is free to ignore it.
I checked the difference between abs and fabs on python here
As I understand there are some difference regarding the speed and the passed types, but my question related to native c++ on V.S.
Regarding the V.S.
I tried the following on Visual Studio 2013 (v120):
float f1= abs(-9.2); // f = 9.2
float f2= fabs(-9); // Compile error [*]
So fabs(-9) it will give me a compiler error, but when I tried to do the following:
double i = -9;
float f2= fabs(i); // This will work fine
What I understand from the first code that it will not compile because fabs(-9) need a double, and the compiler could not convert -9 to -9.0, but in the second code the compiler will convert i=-9 to i=-9.0 at compile time so fabs(i) will work fine.
Any better explanation?
Another thing, why the compiler can't accept fabs(-9) and convert the int value to double automatically like what we have in c#?
[*]:
Error: more than one instance of overloaded function "fabs" matches the argument list:
function "fabs(double _X)"
function "fabs(float _X)"
function "fabs(long double _X)"
argument types are: (int)
In C++, std::abs is overloaded for both signed integer and floating point types. std::fabs only deals with floating point types (pre C++11). Note that the std:: is important; the C function ::abs that is commonly available for legacy reasons will only handle int!
The problem with
float f2= fabs(-9);
is not that there is no conversion from int (the type of -9) to double, but that the compiler does not know which conversion to pick (int -> float, double, long double) since there is a std::fabs for each of those three. Your workaround explicitly tells the compiler to use the int -> double conversion, so the ambiguity goes away.
C++11 solves this by adding double fabs( Integral arg ); which will return the abs of any integer type converted to double. Apparently, this overload is also available in C++98 mode with libstdc++ and libc++.
In general, just use std::abs, it will do the right thing. (Interesting pitfall pointed out by #Shafik Yaghmour. Unsigned integer types do funny things in C++.)
With C++ 11, using abs() alone is very dangerous:
#include <iostream>
#include <cmath>
int main() {
std::cout << abs(-2.5) << std::endl;
return 0;
}
This program outputs 2 as a result. (See it live)
Always use std::abs():
#include <iostream>
#include <cmath>
int main() {
std::cout << std::abs(-2.5) << std::endl;
return 0;
}
This program outputs 2.5.
You can avoid the unexpected result with using namespace std; but I would adwise against it, because it is considered bad practice in general, and because you have to search for the using directive to know if abs() means the int overload or the double overload.
My Visual C++ 2008 didn't know which to choice from long double fabs(long double), float fabs(float), or double fabs(double).
In the statement double i = -9;, the compiler will know that -9 should be converted to double because the type of i is double.
abs() is declared in stdlib.h and it will deal with int value.
fabs() is declared in math.h and it will deal with double value.