こんばんは、Qt Advent Calendar 2020の 3日目の記事です。
小ネタです。
CやC++を使用している時に、浮動小数点の比較や各種演算を行う場合、標準Cライブラリであるfloat.hやmath.hを使用しますよね。
Qtを使用しているのにその時のクセで同じように書いてしまうことってありますよね…ありませんか?
コンパイラにmsvcを使用している時はそのままビルドを通すことができますが、MinGWやEmscriptenではfloat.hやmath.hが使用できません。
そんな時の対処法です。
一般的な数学関数
#include <math.h>
{
double result = std::pow(2.0,2.0);
}
#include <QtMath>
{
double result = qPow(2.0,2.0);
}
結果はどちらも4になります。
qPowは中でstd::powを呼んでいます。最初記事のタイトルを「Qtで行う標準Cライブラリに頼らない演算処理」にしていたんですが、書いていて頼っているなと思いタイトルを変更しました。
QtMathはqmath.hをインクルードしており、qmath.hはcmathを、cmathはmath.hをインクルードしています。
math.hの主要な演算関数はqmath.h内でq〇〇という名前で実装されています。
浮動小数点数の比較
#include <float.h>
#include <math.h>
{
double a = 1.0, b = 1.0;
b += 0.001;
b -= 0.001; // 誤差発生
bool result1 = std::fabs(a - b) <= DBL_EPSILON;
}
#include <QtGlobal>
#include <QtMath>
{
double a = 1.0, b = 1.0;
b += 0.001;
b -= 0.001; // 誤差発生
bool result2 = qFuzzyCompare(a,b);
}
結果はどちらもtrueになります。
qFuzzyCompareは浮動小数点数の比較関数です。
ただ、QtGlobalのリファレンスに書いてある通り厳密な比較ではないですし、注意書きもいくつかあるので、自分の必要な精度の処理かは適宜調べてから使用していください。
事の発端
普段msvcを使用していて、WebAssemblyを使用してアプリを移植しようとしている時にコンパイラがMinGWEmscriptenになり発覚しました。
通常はMinGWをコンパイラに使用することが多いでしょうし、本来最初の方に発覚することでしょうか?
#追記
正確には、
・msvcは標準Cライブラリをインクルードしなくても使用可
・MinGWは標準Cライブラリをインクルードすれば使用可
・Emscriptenは標準Cライブラリはインクルード不可
でした。