开发者

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 doubles) and sqrtf for floats.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜