Разница между sqrt и sqrtf - PullRequest
       23

Разница между sqrt и sqrtf

13 голосов
/ 15 сентября 2011

Я хочу рассмотреть код.Сначала это:

#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;
int main() {
    int s = 25;
    cout << sqrt(s) << endl;
    return 0;
}

Это дало мне эту ошибку:

>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 ==========

Если я добавлю тип float в скобках перед s, например:

#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;

int main() {
    int s = 25;
    cout << sqrt((float)s) << endl;
    return 0;
}

Я получил, как я предполагаю, 5.И еще один вариант: вместо sqrt, если я напишу sqrtf:

#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;

int main(){
    int s=25;
    cout << sqrtf((float)s) << endl;
    return 0;
}

, я тоже получил 5.

В чем разница между ними?Означает ли это, что sqrtf совпадает с sqrt для типа float?

Ответы [ 5 ]

16 голосов
/ 15 сентября 2011

Вот страница документации MSDN для sqrt() и sqrtf(), объясняющая разницу:

sqrt, sqrtf

Вычисляет квадратный корень.

    double sqrt(
       double x 
    );
    float sqrt(
       float x 
    );  // C++ only
    long double sqrt(
       long double x
    );  // C++ only
    float sqrtf(
       float x 
    );

Параметры

x : неотрицательное значение с плавающей точкой

Замечания

C ++ допускает перегрузку, поэтому пользователи могут вызывать перегрузки sqrt , которые принимают типы с плавающей запятой или длинные двойные типы.В программе на Си sqrt всегда принимает и возвращает значение double.

Возвращаемое значение

Функция sqrt возвращает квадраткорень х.Если x отрицательно, sqrt возвращает неопределенное значение по умолчанию.

Таким образом, разница в C ++ состоит в том, что sqrt() принимает либо double, float илиlong double, в то время как sqrtf() принимает только float.

Как сказано в документации, единственная причина, по которой существует две разные версии, заключается в том, что C не поддерживает перегрузку, поэтому должно быть две функции.C ++ допускает перегрузку, поэтому на самом деле есть три разные версии sqrt(), принимающие аргументы с плавающей запятой разных размеров.

Так что в C ++ оба ваших фрагмента кода по сути делают одно и то же.На C, однако, в вызове sqrt() произошло бы преобразование из float в double.

3 голосов
/ 15 сентября 2011

В C ++ функция sqrt перегружена, чтобы принимать либо double, float или long double в качестве аргумента.Когда вы передаете int, все три могут быть вызваны, и компилятор не может выбрать один из них, поэтому вызов неоднозначен.Если вы явно конвертируете int в float, конечно, одно из трех является точным соответствием, что делает его лучше, чем два других, поэтому его вызывают.из C;в С нет перегрузок;sqrt всегда sqrt(double), а sqrtf занимает float.Поскольку эта функция не перегружена, ее вызов не может привести к неоднозначности.

3 голосов
/ 15 сентября 2011

C не поддерживает перегрузку функций.Это означает, что должна быть одна отдельная функция для каждого типа.Следовательно, sqrt для double и sqrtf для float.Поскольку double был «предпочтительным» типом для чисел с плавающей запятой в C, то «стандартной» была версия для double.Оба являются частью стандартной библиотеки C, в math.h.

В C ++ следует использовать перегруженный sqrt (определенный в cmath, в пространстве имен std).

2 голосов
/ 15 сентября 2011

sqrtf является наследием C.

В C ++ мы имеем перегрузку, а функция sqrt имеет разные перегрузки для трех типов с плавающей запятой.В C, напротив, нет перегрузки, поэтому различные версии функции квадратного корня должны различаться по имени функции;следовательно, у нас есть sqrt (что в C работает только на double с) и sqrtf для float с.

0 голосов
/ 09 мая 2018

sqrtf() быстрее, чем sqrt()

... но вы точно платите цену.

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

NB Я использовал несколько сумасшедших флагов компилятора, чтобы выделить разницумое оборудование.Если вы действительно не знаете, что делаете, возможно, вам следует использовать более консервативные флаги.

...