ライブラリ: 数学ユーティリティ - ページ 6

 
キャストされた(文字列)dblと全く同じ最短文字列を得るためにカスタム関数が必要な場合は、ライブラリのRepr()関数を使用してください:

string shortest_str = Repr(dbl) .

この関数は、MQLの開発者がstringとPrint()のバグを修正し、iee-754標準に準拠させる前に必要とされていました。
 

あなたが正しくて、そんなに簡単なことならいいんだけど。そんな簡単なことなら、私はここにいないし、間違いなくこんなことに多くの労働時間を浪費していない。


確かに、私は以下のことが必要だ:

1. 小数点以下の桁数をコントロールする。

2. 動的に桁数を調整し、可能な限り短くする。


私のダブルは次のようなものです。

Tickvalue ->SYMBOL_TRADE_TICK_VALUE

TickSize -> SYMBOL_TRADE_TICK_SIZE

そして

LotValue = ((TickValue / TickSize) * lot);


変なところはなく、標準的な値で、すべて良好ですが、LotValueはフォーマットしにくく、画面に表示しにくいようです。


大きな問題は、私のダブルスは1.000000000と表示されますが、実際には1.000000001です。

(私はダブルスの仕組みを知っており、それが正常であることを理解しています)


Print()、DoubleToString()、NormalizeDoubles()、StringFormat()は基本的に数値を丸めるため、結果の数値はひどく間違っています。

(常に価格を表示するアプリケーションにとって、1.04966から1.0497に変換された'偽装'された数値を見るのが便利な状況というのは思いつかないが、それはまた別の日に議論することにしよう)。


そういうわけで、最初は単純な計算式を使って目的の精度を得ようとしていました。

int p = 5; // 希望の精度

double n = 1.000000000;

double p10 = (p * 10);

double(long(n * p10) / p10);

しかし、Forexの代わりにCryptoで9-10という高い精度が必要になり、それ以上の精度では末尾のゼロを取り除くことができなかったので、御社の関数にたどり着きました。

このような問題が発生するのは、できるだけ多くの情報をユーザーに出力する必要があり、画面のスペースが限られているため、数字を一定のスペースに収めなければならないからです。


あなたの関数Trunc()は99.9%の数値に対してトリックを実行しますが、いくつかの数値はうまくいかず、特別な処理が必要です。

それを行うための削減された式を教えてくれることを期待していました。


さらに、Round(double, int)関数が、ある2倍数でMT4の実行を停止してしまいます。doubleはそれほど大きくなく、100000.0000000000です。

これはEURUSDの1Lotの値を表す一般的な数値で、値を手書きすればすべてOKなのですが、LotValue = ((TickValue / TickSize) * lot);という計算をするとMT4がブロックしてしまいます。


こんな単純な作業にすでに40時間以上費やしている。もう死にそうです!

 
Cristian Dan Fechete #:

そうする必要があるのは事実だ:

1. 小数点以下の桁数を制御する。

2. 動的に桁数を調整し、可能な限り短くする。


私はこう言った
double n = 1.000000000;
と同じである:
double n = 1.0;

あなたの要求
文字列内の小数 <= 指定された桁数

もしあなたの要求が、(小数点の最大桁数を制御しながら)末尾に0を付けずにできるだけ短い文字列に数値をフォーマットすることだけであれば、次のようになります:

string s1 = (string) Round(number, digits);

string s2 = (string) NormalizeDouble(number, digits);

string s3 = StringFormat("%.5f", number);
任意の形式を選択してください。

RoundとNormalizeDoubleは小数点以下の最大桁数を制御します。そして、文字列(string)dblにキャストすると、末尾のゼロを除いた可能な限り短い文字列が得られます。StringFormat()も同じことをしますが、コードの中で何百万回も呼び出されると少し遅くなるようです。

あなたの場合、DoubleToString() はお勧めできません。なぜなら、より短い文字列 < 桁に末尾の 0 をつけて、小数点以下の桁数を固定にしてしまうからです。それは、あなたが求めているものではありません。あなたが求めているのは、動的な小数点以下の桁数(最短の桁数)です。

編集
精度の計算を次のように間違えています。
int p = 5; // 求める精度
double p10 = (p * 10);

と計算すべきです:
int p = 5; // 求める精度
double p10 = MathPow(10, p);

 

4回メッセージを送っても、私の問題を理解してもらえなかったようで、自分の失敗にひどく失望しています。

そして、このサイトのスタイライザーは完全にバグっているので、ここで適切にメッセージを書くのは非常に時間がかかります。

double n = 1.000000000; 
should be the same as:
double n = 1.0;
but it is NOT

理由は説明できませんが、1.000000000;は0以外の小数点がどこかにあると考えなければなりません。

しかし、結果はこうだ:

string s1 = (string) Round(number, digits);  -> blocks MT4

string s2 = (string) NormalizeDouble(number, digits); -> returns a 'faked' string where a rounding is done on last digit

string s3 = StringFormat("%.5f", number); -> same as NormalizeDouble()

19.65400のような数字の場合

string s = (string) Trunc(number, digits);

は完璧に機能する。また、手動で1.0000000を入力しても完璧に動作します。

この関数は400以上の異なるパラメーターで使用し、それぞれのパラメーターは各ティックで異なる値を持ち、Trunc()は完璧に動作します。

しかし

double lotValue = ((_TickValue / _TickSize) * lot);

そのため、Round(number, digits);という関数も入れていて、それでうまくいっていたのですが、私の関数Normalize_Double_ToString()をよりシンプルで最適化されたコードにまとめる公式があるかどうか、あなたに尋ねようと思ったのです。

そして、あなたは全く異なることを私に答えました(適切に説明しなかったのは完全に私のせいだと仮定します)。

しかし、昨日からRound()がMT4をブロックしており、Roundなしでは小数側の有効桁数を正しくカウントできません。

問題はlongへのタイプキャストのようです。Round(double,int);からこれを取り除くと、MT4は問題なく実行されるのですが、6桁の整数桁を持つdoubleに10000を掛けたものが、どのようにしてlongの限界に達するのかがわかりません。


この時点で私の疑問は

出口はどこですか?


いずれにせよ、私はこの問題を解決しなければならない。

 

これを試してみてほしい:

string Normalize_Double_ToString(double n, int d)
{
   n = Round(n, d);
   d = MathMin(d, GetDigits(n);

   return DoubleToString(n, d);
}

ただし、 前の投稿にある3つの短い方法よりはるかにうまくはいかないだろう。

注意してください、

私は自分のライブラリのRound()を使っています:

n = NormalizeDouble(n, d);

しかし、Round()にエラーがあるというのは疑わしい。
 
Cristian Dan Fechete #:

4回メッセージを送っても、私の問題を理解してもらえなかったようで、自分の失敗にひどく失望しています。

それに、このサイトのスタイライザーは完全にバグっているので、ここにきちんとメッセージを書くのはとても時間がかかるのです。

理由は説明できませんが、1.000000000;は0以外の小数点がどこかにあると考えなければなりません。

MT4でお困りの原因はよくわかりました。

期待した結果が得られない主な原因は、MQL4のstring(dbl)のバグで、MT4ではまだ修正されていません。

MQL4のstring()関数のバグ。double→文字列の間違った変換。

これは、Print()、Alert()、Comment()、FileWrite()による(暗黙の文字列へのキャストによる)doubleの表示方法にも影響します。

このバグはMT5では修正されましたが、MT4では修正されていません。こちら(https://www.mql5.com/en/forum/367839/page3#comment_27477157)と こちら(https://www.mql5.com/en/forum/367839/page5#comment_27613205)の修正を参照してください。

私の推奨

MT4でダブルスを文字列として深く掘り下げたりデバッグしたりする場合は、math_utils.mqhのRepr()関数を 使用して、常に文字列への明示的なキャストを強制してください。

#include "math_utils.mqh"

//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
void OnStart()
  {
   double a = 1.0000000000000002;
   Print(a);         //1.0 (double -> string の暗黙のキャストのバグ)
   Print(Repr(a));   // 1.0000000000000002

   double b = 100.00000000000003;
   Print(b);         //100.0 (double -> stringの暗黙キャストのバグ)
   Print(Repr(b));   // 100.00000000000003
  }
MT5/mql5 reported and confirmed bugs. - Custom ZERO Level Showing ZERO level, bug in MML. String(MQ)
MT5/mql5 reported and confirmed bugs. - Custom ZERO Level Showing ZERO level, bug in MML. String(MQ)
  • 2022.02.01
  • Alain Verleyen
  • www.mql5.com
On indicators, mt5 can set automatically a level "0" depending of the buffer values. Custom indicator showing zero level, though not defined anywhere in the code. Wrong conversion of double -> string. Then test the same example in your browser js pad or any online javascript pad and check the difference