Difference between sqrt and sqrtf
I want to consider to code. First it is:
#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;
int main() {
int s = 25;
cout << sqrt(s) << endl;
return 0;
}
It gave me this mistake:
>c:\users\datuashvili\documents\visual studio 2010\projects\training\training\training.cpp(9): error C2668: 'sqrt' : ambiguous call to overloaded function
1> c:\program files\microsoft visual studio 10.0\vc\include\math.h(589): could be 'long double sqrt(long double)'
1> c:\program files\microsoft visual studio 10.0\vc\include\math.h(541): or 'float sqrt(float)'
1> c:\program files\microsoft visual studio 10.0\vc\include\math.h(127): or 'double sqrt(double)'
1> while trying to match the argument list '(int)'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
If I add type float in brackets in front of s, like this:
#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;
int main() {
int s = 25;
cout << sqrt((float)s) << endl;
return 0;
}
I got as I would guess, 5
. And another variant is that instead of sqrt
, if I write sqrtf
:
#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;
int main(){
int s=25;
cout << sqrtf((float)s) << endl;
retu开发者_如何转开发rn 0;
}
I also got 5
.
What is the difference between them? Does it means that sqrtf is same as sqrt for the float type?
Here's a page on MSDN documentation for sqrt()
and sqrtf()
, that explains the difference:
sqrt, sqrtf
Calculates the square root.
double sqrt( double x ); float sqrt( float x ); // C++ only long double sqrt( long double x ); // C++ only float sqrtf( float x );
Parameters
x: Nonnegative floating-point value
Remarks
C++ allows overloading, so users can call overloads of sqrt that take float or long double types. In a C program, sqrt always takes and returns double.
Return Value
The sqrt function returns the square-root of x. If x is negative, sqrt returns an indefinite, by default.
So the difference in C++ is that sqrt()
accepts either a double
, a float
or a long double
while sqrtf()
accepts only a float
.
As the documentation says, the only reason why there's two different versions is because C did not support overloading, so there had to be two functions. C++ allows overloading, so there are actually three different versions of sqrt()
taking floating point arguments of various sizes.
So in C++, both your code snippets do essentially the same thing. On C, however, there would've been a conversion from float
to double
in the sqrt()
call.
C did not support function overloading. That means that there had to be one different function for each type. Hence a sqrt
for double
and sqrtf
for float
. Since double
was the "preferred" type for floating point numbers in C, then the "default" version was the one for double
. Both are part of the C standard library, in math.h
.
In C++, the overloaded sqrt
(defined in cmath
, in namespace std
) should be used.
In C++, the sqrt
function is overloaded to take either a double
, a
float
or a long double
as argument. When you pass an int
, all
three can be called, and there's no way for the compiler to choose one
over the others, so the call is ambiguous. If you explicitly convert
the int
to float
, of course, one of the three is an exact match,
whcih makes it better than the other two, so it gets called.
The function sqrtf
is from C; in C, there is no overloading; sqrt
is
always sqrt(double)
, and sqrtf
takes a float
. Since this function
isn't overloaded, calling it can't result in an ambiguity.
sqrtf
is a heritage of C.
In C++ we have overloading, and the sqrt
function has different overloads for the three floating-point types. In C, instead, there's no overloading, thus the various versions of the square root function must be distinguished with the name of the function; hence we have sqrt
(that in C works only on double
s) and sqrtf
for float
s.
sqrtf()
is faster than sqrt()
...but you pay a price in precision.
C:\Users\ceilingcat> type f.cc
#include<iostream>
#include<cmath>
int main(){
double f=0;
int i=0;
for( ; i <= 2000000000; f+=sqrt(i++) );
std::cout.precision( 20 );
std::cout<<f<<'\n';
}
C:\Users\ceilingcat> cl f.cc /Ox /arch:AVX2 /fp:fast /Qfast_transcendentals
C:\Users\ceilingcat> time ./f.exe
59628479422355.53125
real 0m3.846s
user 0m0.000s
sys 0m0.015s
C:\Users\ceilingcat> type g.cc
#include<iostream>
#include<cmath>
int main(){
double f=0;
int i=0;
for( ; i <= 2000000000; f+=sqrtf(i++) );
std::cout.precision( 20 );
std::cout<<f<<'\n';
}
C:\Users\ceilingcat> cl g.cc /Ox /arch:AVX2 /fp:fast /Qfast_transcendentals
C:\Users\ceilingcat> time ./g.exe
59628479422157.773438
real 0m2.104s
user 0m0.000s
sys 0m0.000s
N.B. I used some crazy compiler flags to highlight the difference on my hardware. Unless you really know what you're doing, you should probably use more conservative flags.
精彩评论