浮動小数点型(
double , float)は小数点以下の小さな値を表現する事が出来ます。
MQL4言語では2つの浮動小数点型が使用できます。
コンピュータ・メモリの実数表現のメソッドは、
IEEE754(浮動小数点数演算標準)によって定義されており、
プラットホーム・オペレーティングシステム・プログラミング言語から独立しています。
型 |
データサイズ [Byte] |
正数の最小値 |
正数の最大値 |
精度 [有効桁数) |
float |
4 |
1.175494351e-38 |
3.402823466e+38 |
7桁 |
double |
8 |
2.2250738585072014e-308 |
1.7976931348623158e+308 |
15桁 |
doubleの名称はfloat型の精度が倍である事を意味します。
floatは精度が限定されていて十分な結果を得られない事がある為、ほとんどの場合
doubleを使用します。
floatが使用される理由は、メモリの使用量が
doubleの半分だからです。
浮動小数点数型の大きな動的配列を使用する時、
限定された精度のデータを取り扱う場合に
floatを使用するとメモリ消費を抑えられます。
浮動小数点定数は、整数と小数点と少数で成り立ちます。
整数と少数は10進数の連続した数値で表します。
サンプルソース:
double tmp_double;
float tmp_float;
tmp_double = 12.111;
tmp_double = -956.1007;
tmp_float = 0.0001;
tmp_float = 16;
float tmp_array_float[999999];
ArrayInitialize( tmp_array_float , 0 ));
float[0] = 0.25;
浮動小数点数型は、2進数の限られた精度でメモリに保存される事に注意しなければなりません。
小数点以下の誤差について
浮動小数点数型は
IEEE754(外部リンク)のメソッドで実数を表現しており、
小数点以下の数値は近似値に丸められてしまい誤差が発生する場合があります。
なのでif文判定での等価判定や、
整数型へキャストする場合は十分注意して下さい。
極端な事を言えば、
2の累乗用いて小数点以下のデータを保存している為、精度の範囲内(
2のべき乗(外部リンク))で割り切れる値は正確に保存されますが、
精度の範囲内で割り切れない値は誤差が生じます。
例えば 0.5 , 0.25 , 0.125・・・では誤差は生じません。
その組み合わせの0.75 , 0.625・・・でも誤差は生じません。
しかし、0.1 , 0.05 , 0.7等の値は
循環小数(外部リンク)による誤差が発生し、
コンピュータは0.10000000000000001 , 0.050000000000000003 , 0.69999999999999996 という近似値で表現します。
あくまで極端な例です。厳密に言えばそんな単純ではありません。
詳細は
IEEE754(外部リンク)を参照して下さい。
気をつけなければならないのは、近似値同士の値の算出結果を
int型へのキャストや
MathFloor()で小数点以下を切り捨てる場合です。
サンプルソース:
double temp_div = 0.7 / 0.1;
Print( "0.7 / 0.1 = " , (int)temp_div);
結果
0.7 / 0.1 = 6
これは近似値同士の除算によって算出結果も近似値になってしまう為、
0.69999999999999996 / 0.10000000000000001 = 6.9999999999999991
算出結果の近似値6.9999999999999991の小数点以下を切り捨てる事で結果が6になってしまいます。
解決策としては、除算の際に分子と分母を10倍する等の方法が一般的です。
サンプルソース:
const double div_times = 10;
double temp_div = ( 0.7 * div_times) / ( 0.1 * div_times );
Print( "0.7 / 0.1 = " , (int)temp_div);
結果
0.7 / 0.1 = 7
サンプルソース:
double tmp_double_a;
double tmp_double_b;
double tmp_double_c;
double tmp_double_div;
tmp_double_div = 4.0;
tmp_double_a = 1 / tmp_double_div;
tmp_double_b = 2 / tmp_double_div;
tmp_double_c = 3 / tmp_double_div;
if ( ( tmp_double_a + tmp_double_b) == tmp_double_c ) {
Print("一致");
} else {
Print("不一致");
}
tmp_double_div = 3.0;
tmp_double_a = 1 / tmp_double_div;
tmp_double_b = 4 / tmp_double_div;
tmp_double_c = 5 / tmp_double_div;
if ( ( tmp_double_a + tmp_double_b) == tmp_double_c ) {
Print("一致");
} else {
Print("不一致");
}