MathClassify関数の働き・役割
MathClassify関数は、指定された浮動小数点数の型を判別し、その分類結果をENUM_FP_CLASS列挙体の値として返します。
この関数は、数値が通常の浮動小数点数であるか、無限大、ゼロ、非数(NaN)などの特殊な状態であるかを確認するために使用されます。数値計算や精度管理が重要な場合に、値の状態を適切に把握し、エラー処理や条件分岐に活用することができます。
ENUM_FP_CLASSについて
ENUM_FP_CLASSは、MathClassify関数によって返される列挙型で、浮動小数点数の型を以下の識別子で定義しています。それぞれの識別子は、特定の浮動小数点数の種類を表しています。
FP_SUBNORMAL
FP_SUBNORMALは表現可能な最小の正規数であるDBL_MIN(約2.2250738585072014e-308)よりも小さく、ゼロに近い「非正規数」を表します。計算誤差や小数点精度の確認に役立つ識別子です。
FP_NORMAL
FP_NORMALは通常の浮動小数点数として、約2.2250738585072014e-308から約1.7976931348623158e+308の範囲にある正規数を表します。この範囲に収まる一般的な数値が分類されます。
※e+308やe-308という表記は「指数表記」と呼ばれ、大きな数や小さな数を簡単に表すための方法です。
例えば、2.2250738585072014e-308は「2.2250738585072014 × 10のマイナス308乗」を意味します。これは非常に小さな数です。同様に、1.7976931348623158e+308は「1.7976931348623158 × 10の308乗」を表し、非常に大きな数となります。この指数表記を使うことで、大きすぎたり小さすぎたりする数を短い形で表現できます。
FP_ZERO
FP_ZEROは正または負のゼロを表します。ゼロであっても符号が保持されるため、符号付きのゼロを識別する際に利用できます。
FP_INFINITE
FP_INFINITEは正の無限大または負の無限大を表します。計算結果が無限大に達した場合や、計算範囲を超える際に確認される状態です。
FP_NAN
FP_NANは「Not a Number(NaN)」で、数値として定義できない値を表します。除算エラーなど、数学的に不正な操作が実行された際にNaNが生成される場合があります。
MathClassify関数の引数について
MathClassify関数の引数は以下の通りです。
書式
ENUM_FP_CLASS MathClassify(
double value // 浮動小数点数
);
引数の説明
- value
- 種類: 浮動小数点数型(double)
- 説明: 判別対象の浮動小数点数を指定します。この引数に指定された数値が、通常の数値か、特殊な値(ゼロ、無限大、非数など)であるかが判定されます。
MathClassify関数の戻り値について
MathClassify関数の戻り値は、ENUM_FP_CLASS列挙体のいずれかの値です。この戻り値によって、指定された浮動小数点数がどのような型であるかがわかります。
MathClassify関数を使ったサンプルコード
//+------------------------------------------------------------------+
//| スクリプトプログラムの開始関数 |
//+------------------------------------------------------------------+
void OnStart()
{
//--- NaN(数ではない)をテスト
// NaNは数値として扱えない特殊な値を表します
double nan = double("nan");
PrintFormat("テスト NaN: %G は %s です, MathIsValidNumber(NaN)=%s",
nan,
EnumToString(MathClassify(nan)),
(string)MathIsValidNumber(nan)); // NaNかどうかの確認を出力
//--- 無限大の値をテスト
// infは正または負の無限大を表す特殊な値です
double inf = double("inf");
PrintFormat("テスト 無限大: %G は %s です, MathIsValidNumber(inf)=%s",
inf,
EnumToString(MathClassify(inf)),
(string)MathIsValidNumber(inf)); // 無限大かどうかの確認を出力
//--- 正常な(通常の)数値をテスト
// 通常の範囲内にある浮動小数点数
double normal = 1.2345e6;
PrintFormat("テスト 通常の値: %G は %s です, MathIsValidNumber(normal)=%s",
normal,
EnumToString(MathClassify(normal)),
(string)MathIsValidNumber(normal)); // 通常の数値かどうかの確認を出力
//--- 非正規数をテスト
// 非正規数とは、正規の最小値より小さい数を意味します
double sub_normal = DBL_MIN / 2.0;
PrintFormat("テスト 非正規数: %G は %s です, MathIsValidNumber(sub_normal)=%s",
sub_normal,
EnumToString(MathClassify(sub_normal)),
(string)MathIsValidNumber(sub_normal)); // 非正規数かどうかの確認を出力
//--- ゼロの値をテスト
// ゼロ(符号付きゼロも含む)を判別
double zero = 0.0 / (-1); // -0 を生成
PrintFormat("テスト ゼロ: %G は %s です, MathIsValidNumber(zero)=%s",
zero,
EnumToString(MathClassify(zero)),
(string)MathIsValidNumber(zero)); // ゼロかどうかの確認を出力
}
/*
結果:
テスト NaN: NAN は FP_NAN です, MathIsValidNumber(NaN)=false
テスト 無限大: INF は FP_INFINITE です, MathIsValidNumber(inf)=false
テスト 通常の値: 1.2345E+06 は FP_NORMAL です, MathIsValidNumber(normal)=true
テスト 非正規数: 1.11254E-308 は FP_SUBNORMAL です, MathIsValidNumber(sub_normal)=true
テスト ゼロ: -0 は FP_ZERO です, MathIsValidNumber(zero)=true
*/
//+------------------------------------------------------------------+
サンプルコード解説1: OnStart関数部分その1
//+------------------------------------------------------------------+
//| スクリプトプログラムの開始関数 |
//+------------------------------------------------------------------+
void OnStart()
{
//--- NaN(数ではない)をテスト
// NaNは数値として扱えない特殊な値を表します
double nan = double("nan");
PrintFormat("テスト NaN: %G は %s です, MathIsValidNumber(NaN)=%s",
nan,
EnumToString(MathClassify(nan)),
(string)MathIsValidNumber(nan)); // NaNかどうかの確認を出力
このサンプルコードは、MQL5のスクリプトで浮動小数点数の型を判別するために使用されるMathClassify関数をテストしています。ここでは、OnStart関数の中で、特殊な浮動小数点数である「NaN(Not a Number、数ではない)」の状態を確認しています。
OnStart関数
OnStart関数は、スクリプトが実行されたときに自動的に呼び出される関数です。ここでは、特定の数値の状態を確認するための処理が記述されています。
NaN(数ではない)についてのテスト
- NaNの生成
NaN(Not a Number)は、数として認識されない特殊な値です。例えば、不正な数値計算(0での除算や無効な関数の引数)によって生成されます。このコードでは、double関数で文字列「nan」を指定し、NaNを生成しています。
※double(“nan”);という表記は、文字列 “nan” を double型に変換するために使われています。これは、キャストの一種であり、特定の文字列を浮動小数点数の特殊な値(NaN: Not a Number、数ではない状態)に変換するための操作です。一般的に、nanという文字列をdouble型に変換すると、「数値ではない」ことを示すNaNとして扱われます。NaNは、計算上で定義できない結果(例:0での除算など)や、エラーのある値を示すために使用されます。double関数を使ってnanを生成することで、数値の型や計算エラーを確認するテストにも使われる表現です。 - MathClassify関数でのNaN判定
MathClassify関数を使用し、生成されたnanがどのような型かを確認しています。この関数は、数値がNaNかどうかを判断し、その結果をENUM_FP_CLASS列挙体の値として返します。NaNの場合、戻り値はFP_NANとなります。 - PrintFormat関数での出力
PrintFormat関数を使って、テスト結果を出力しています。出力される内容は以下の通りです。
- nanの値(NAN)
- MathClassify関数の判別結果(FP_NAN)
- MathIsValidNumber関数によるNaNの有効性チェック結果
MathIsValidNumber関数について
MathIsValidNumber関数は、指定した数値が「有効な実数」かどうかをチェックします。正の無限大や負の無限大、またはNaNである場合にはfalseを返し、通常の数値であればtrueを返します。NaNが無効な数値であるため、この場合はfalseが出力されます。
サンプルコード解説2:OnStart関数部分その2
//--- 無限大の値をテスト
// infは正または負の無限大を表す特殊な値です
double inf = double("inf");
PrintFormat("テスト 無限大: %G は %s です, MathIsValidNumber(inf)=%s",
inf,
EnumToString(MathClassify(inf)),
(string)MathIsValidNumber(inf)); // 無限大かどうかの確認を出力
この部分のコードでは、浮動小数点数の特殊な値である「無限大」を扱っています。無限大とは、正の無限大や負の無限大のことを指し、通常の数値計算で扱えない大きさの数値です。この値を用いてMathClassify関数がどのように動作するかを確認しています。
無限大の生成とテスト
ここでは、文字列 “inf” をdouble型に変換することで無限大を生成しています。この変換によってinfという変数には無限大の値が格納されます。無限大は、特に数学的な計算で数が極端に大きくなりすぎた場合や、範囲外の値が求められたときに出現することが多い特殊な値です。
PrintFormat関数の使用とフォーマット指定子
PrintFormat関数を使って、無限大のテスト結果をエキスパートログに出力しています。PrintFormat関数では、フォーマット指定子を使って値の出力形式を指定します。ここで使われている指定子と、それに対応する値について説明します。
- %G は浮動小数点数を出力する指定子で、通常の数値や無限大、NaNのような特殊な値も出力します。この指定子に対応する値はinfです。ここではinfが無限大の値として表示されます。
- %s は文字列を出力する指定子です。ここではEnumToString関数によって取得された文字列が出力されます。EnumToString関数は、MathClassify関数が返す列挙体の識別子(例えばFP_INFINITEなど)を文字列に変換します。これにより、無限大の型がわかりやすく文字列として出力されます。
- MathIsValidNumber関数の結果も出力されています。この関数は、無限大が有効な数値かどうかをチェックします。ここで得られる結果は無限大の数値ではないためfalseとなり、出力されるのは文字列“false”です。
変換された文字列の出力
上記の各指定子に対応する値によって、無限大のテスト結果がエキスパートログに出力されます。この一連のコードによって、無限大の値が正常に判別されていることを確認でき、MathClassify関数やMathIsValidNumber関数がどのように機能するかを理解する助けとなります。
サンプルコード解説3:OnStart関数部分その3
//--- 正常な(通常の)数値をテスト
// 通常の範囲内にある浮動小数点数
double normal = 1.2345e6;
PrintFormat("テスト 通常の値: %G は %s です, MathIsValidNumber(normal)=%s",
normal,
EnumToString(MathClassify(normal)),
(string)MathIsValidNumber(normal)); // 通常の数値かどうかの確認を出力
この部分のコードでは、通常の範囲内にある浮動小数点数を使って、MathClassify関数がどのように分類するかをテストしています。ここで使用されている数値は「1.2345e6」で、これは「1.2345 × 10の6乗」、つまり1234500という値を表します。指数表記を使うことで、大きな数や小さな数を短く簡潔に表現しています。
通常の数値の生成とテスト
double型の変数normalに「1.2345e6」という通常の範囲内の数値を代入し、MathClassify関数で分類を行っています。MathClassify関数は、この数値が通常の浮動小数点数(正規数)であると判定します。
※1.2345e6は「1.2345 × 10の6乗」という意味です。つまり、1.2345e6は1234500を表しています。
PrintFormat関数の使用とフォーマット指定子
PrintFormat関数を用いて、テスト結果をエキスパートログに出力しています。この関数では、指定子を使って出力形式を指定しており、それぞれの指定子が異なる値に対応しています。
%G
は浮動小数点数の指定子です。ここでは、normalに代入された通常の数値が表示されます。%G
は、指定された数値が指数表記に適している場合には指数表記で、そうでない場合には通常の小数表記で表示されます。%s
は文字列を出力する指定子です。MathClassify関数の戻り値であるENUM_FP_CLASS列挙体の識別子をEnumToString関数で文字列に変換し、識別結果をわかりやすく表示しています。この場合、MathClassify関数はnormalが通常の数値であることを判別し、戻り値としてFP_NORMALを返します。この結果はEnumToString関数で文字列「FP_NORMAL」として出力されます。- MathIsValidNumber関数は、数値が有効であるかを確認します。通常の数値は有効な数値とみなされるため、結果としてtrueが返され、文字列“true”として表示されます。
変換された文字列の出力
上記の指定子に対応する値によって、正常な数値が正しく判別されていることがエキスパートログに出力されます。このテストによって、通常の数値を扱う場合でもMathClassify関数やMathIsValidNumber関数が正常に動作することが確認できます。
サンプルコード解説4:OnStart関数部分その4
//--- 非正規数をテスト
// 非正規数とは、正規の最小値より小さい数を意味します
double sub_normal = DBL_MIN / 2.0;
PrintFormat("テスト 非正規数: %G は %s です, MathIsValidNumber(sub_normal)=%s",
sub_normal,
EnumToString(MathClassify(sub_normal)),
(string)MathIsValidNumber(sub_normal)); // 非正規数かどうかの確認を出力
この部分のコードでは、通常の浮動小数点数の範囲よりも小さい「非正規数」をテストしています。非正規数とは、正規数(通常の範囲内の数)として表現できない小さな数値を指します。これにより、浮動小数点数の最小値(DBL_MIN)をさらに小さくした値が「非正規数」として分類されることを確認できます。
非正規数の生成とテスト
非正規数を生成するために、DBL_MIN(浮動小数点数で表現できる最小の正規数)を2で割った値をsub_normalに代入しています。この数値は通常の正規数として扱えない小さな値となり、MathClassify関数で非正規数として分類されます。
PrintFormat関数の使用とフォーマット指定子
PrintFormat関数を使用して、エキスパートログに非正規数のテスト結果を出力しています。ここでもフォーマット指定子を使用して、異なるデータを適切に出力しています。
%G
は浮動小数点数を出力する指定子で、通常の数値や特殊な値(無限大や非正規数)も表現します。ここではsub_normalに代入された非正規数の値が表示されます。%Gは指数表記や通常表記の両方で表示可能で、数値に応じて最適な形式を選びます。%s
は文字列を出力する指定子で、MathClassify関数によって返されるENUM_FP_CLASS列挙体の識別子をEnumToString関数で文字列に変換したものが出力されます。このコードではMathClassify関数が非正規数を判別し、FP_SUBNORMALが戻り値として返されます。この結果はEnumToString関数で「FP_SUBNORMAL」という文字列に変換され、ログに表示されます。- MathIsValidNumber関数も使用されています。非正規数は有効な数値と見なされるため、この関数はtrueを返します。この結果は文字列“true”として出力されます。
変換された文字列の出力
上記のフォーマット指定子に基づき、非正規数として判別された結果がエキスパートログに出力されます。このテストにより、MathClassify関数とMathIsValidNumber関数が非正規数に対しても正常に動作することが確認されます。
サンプルコード解説5:OnStart関数部分その5
//--- ゼロの値をテスト
// ゼロ(符号付きゼロも含む)を判別
double zero = 0.0 / (-1); // -0 を生成
PrintFormat("テスト ゼロ: %G は %s です, MathIsValidNumber(zero)=%s",
zero,
EnumToString(MathClassify(zero)),
(string)MathIsValidNumber(zero)); // ゼロかどうかの確認を出力
}
この部分のコードでは、ゼロの値をテストしています。ゼロには「正のゼロ」と「負のゼロ」が存在し、符号が付いたゼロも区別されます。ここでは、負のゼロを生成し、MathClassify関数でその分類を確認しています。
ゼロの生成とテスト
double型の変数zeroに、0.0を-1で割った値を代入しています。これにより、符号が負のゼロ(-0)が生成されます。この符号付きゼロがMathClassify関数で分類され、ゼロとして識別されることを確認します。
PrintFormat関数の使用とフォーマット指定子
PrintFormat関数を使って、ゼロのテスト結果をエキスパートログに出力しています。ここでのフォーマット指定子と、それに対応する値について説明します。
- %G は浮動小数点数を出力する指定子で、通常の数値やゼロを表示します。ここでは、zeroに代入された負のゼロの値が出力されます。%Gは数値がゼロの場合も符号を保持して表示するため、-0のように負のゼロもそのまま表現されます。
- %s は文字列を出力する指定子です。MathClassify関数の戻り値であるENUM_FP_CLASS列挙体の識別子をEnumToString関数で文字列に変換し、判別結果をわかりやすく表示します。この場合、MathClassify関数はゼロの値をFP_ZEROとして識別し、EnumToString関数で「FP_ZERO」という文字列として出力されます。
- MathIsValidNumber関数は、ゼロが有効な数値であるかを確認します。ゼロは有効な数値とみなされるため、結果としてtrueが返され、文字列“true”として出力されます。
変換された文字列の出力
これらの指定子に基づき、ゼロ(符号付きゼロ含む)が正しく判別されていることがエキスパートログに出力されます。このコードによって、MathClassify関数とMathIsValidNumber関数がゼロの値に対しても適切に動作することが確認できます。
補足:正のゼロと負のゼロについて
浮動小数点数の世界では、数値のゼロにも「正のゼロ」と「負のゼロ」の2つの異なる種類があります。どちらも数としての値は0ですが、符号が異なることで、異なる意味合いを持たせることができます。
正のゼロ
正のゼロは、通常のゼロのことを指し、数値0に「+」(プラス)の符号がついている状態です。私たちが日常的に「ゼロ」として使っている値と同じもので、特別な符号を意識することはほとんどありません。コンピュータの内部で正のゼロとして表現されている場合でも、プラスの符号が表示されないので、見た目には単なるゼロとして表示されます。
負のゼロ
負のゼロは、ゼロに「-」(マイナス)の符号がついたものです。計算の途中で0をマイナスで割ったり、ある操作によってマイナスがついた状態のままゼロに到達した場合、負のゼロとして扱われることがあります。負のゼロは見た目には「-0」と表記されますが、数値としては通常のゼロと同じ扱いです。
負のゼロと正のゼロは、計算上での丸め誤差(計算結果をできるだけ正確に表そうとしても生じる小さな誤差)や符号の保持が重要になる特殊な場面で役に立つことがあります。例えば、数値が増える方向なのか、減る方向なのかを示すことで計算の方向性を保持するなど、プログラムの内部で意味がある場合があるため、コンピュータの浮動小数点の世界では区別されています。
MathClassify関数を使ってEAを作る際のアイディア
異常値のフィルタリング
トレードロジックで使用される計算結果やインジケータの値に対して、MathClassify関数を使用し、正常な数値以外(無限大やNaNなど)をフィルタリングすることができます。例えば、インジケータの計算結果が無限大やNaNになってしまった場合、それらの値を使って判断するのではなく、EAがその値を無視したり、再計算を要求したりするような処理を組み込むことができます。これにより、誤ったトレード判断を回避することができ、取引の安定性が向上します。
数値の範囲確認によるアラート設定
非常に小さい数値(非正規数)や、極端に大きな数値(無限大)が計算結果として頻繁に発生する場合、それがトレード判断の信頼性を下げる可能性があるため、アラートを出す機能を追加するのも有用です。たとえば、スプレッドやボラティリティが急激に変動し、計算に異常な値が含まれる場合にトレードを停止する設定を組み込むことで、市場の急変時のリスク管理が可能になります。
特定の数値状態でのトレード停止
浮動小数点数の状態に応じて、トレードの判断を一時停止する条件を設定することができます。たとえば、価格変動が非常に少なく、取引が不安定になる可能性が高いときに、非正規数やゼロが頻繁に検出された場合は、取引を停止する判断をEAに組み込むことができます。こうすることで、低ボラティリティ環境下での無駄なトレードや、予測不能な動きによる損失を避けられる可能性があります。
浮動小数点数の分類結果に基づいたログ出力
EAのデバッグやパフォーマンス分析のために、MathClassify関数を用いて分類結果をログ出力する機能を追加するのも有用です。取引が正常に動作しているか、どのタイミングで異常な数値が発生したかを確認することで、より安定したEAの構築につながります。たとえば、異常値の検出頻度を記録し、それを基にコードの改善を検討することも可能です。
MathClassify関数を用いることで、浮動小数点数の種類に応じた適切な処理をEAに組み込むことができ、安定したトレードロジックの実現に役立てることが可能です。