web-dev-qa-db-ja.com

absとfabの違いは何ですか?

absfabsの違いをチェックしましたpython here

私が理解しているように、速度と渡されたタイプに関していくつかの違いがありますが、私の質問はV.Sのネイティブc ++に関連しています。

V.S.についてVisual Studio 2013 (v120)で次のことを試しました:

_float f1= abs(-9.2); // f = 9.2
float f2= fabs(-9); // Compile error [*]
_

fabs(-9)はコンパイラエラーを発生させますが、次のことを試みたとき:

_double i = -9;
float f2= fabs(i); // This will work fine
_

fabs(-9)にはdoubleが必要であり、コンパイラは-9を-9.0に変換できなかったため、コンパイルされないことを最初のコードから理解していますが、2番目のコードではコンパイラは_i=-9_を変換しますコンパイル時に_i=-9.0_に変更されるため、fabs(i)は正常に動作します。

より良い説明はありますか?

もう1つの理由は、コンパイラがfabs(-9)を受け入れず、C#のようにint値を自動的にdoubleに変換できない理由です。

_[*]:

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)   
_
17
Hazem Abdullah

C++では、_std::abs_は符号付き整数型と浮動小数点型の両方でオーバーロードされます。 _std::fabs_は浮動小数点型のみを扱います(C++ 11より前)。 _std::_は重要であり、レガシーの理由で一般的に使用可能なC関数_::abs_はint!のみを処理することに注意してください。

の問題

_float f2= fabs(-9);
_

int(_-9_のタイプ)からdoubleへの変換がないことではなく、コンパイラーはどの変換を選択するかを知らない(int -> floatdouble、_long double_)これら3つのそれぞれに_std::fabs_があるため。回避策は、int-> double変換を使用するようコンパイラーに明示的に指示するため、あいまいさがなくなります。

C++ 11は、absに変換された整数型のdoubleを返すdouble fabs( Integral arg );を追加することでこれを解決します。どうやら、このオーバーロードは、libstdc ++およびlibc ++を使用したC++ 98モードでも使用できます。

一般に、_std::abs_を使用するだけで、正しいことを行います。 ( 興味深い落とし穴@ Shafik Yaghmour によって指摘されています。C++では、符号なし整数型はおかしなことをします。)

16
Baum mit Augen

私のVisual C++ 2008は、long double fabs(long double)float fabs(float)、またはdouble fabs(double)のどれを選択するかを知りませんでした。

ステートメント_double i = -9;_では、doubleの型がiであるため、コンパイラーは_-9_をdoubleに変換する必要があることを認識します。


abs()は_stdlib.h_で宣言され、int値を処理します。

fabs()は_math.h_で宣言され、double値を処理します。

2
MikeCAT

C++ 11では、abs()のみを使用すると非常に危険です。

#include <iostream>
#include <cmath>

int main() {
    std::cout << abs(-2.5) << std::endl;
    return 0;
}

このプログラムは、結果として2を出力します。 ( ライブで見る

常にstd::abs()を使用します。

#include <iostream>
#include <cmath>

int main() {
    std::cout << std::abs(-2.5) << std::endl;
    return 0;
}

このプログラムは2.5を出力します。

using namespace std;で予期しない結果を避けることができますが、一般的に悪い習慣と見なされているため、usingディレクティブを検索してabs()intを意味するかどうかを知る必要があるため、オーバーロードまたはdoubleオーバーロード。

2
alain