MQL4およびMQL5でDigits()をバイパスして任意の数値(引用符だけでなく)の小数点以下桁数を取得 - ページ 7

 

ハブの記事をもとにhttps://habr.com/company/xakep/blog/257897/

#property copyright "IgorM"
#property link      "https://www.mql5.com/ru/users/igorm"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   double a=1.123456;
   Print(DoubleToDigits(a));
  }
//+------------------------------------------------------------------+
int DoubleToDigits(double value)
  {
   const double digits[18]={1 e17,1 e16,1 e15,1 e14,1 e13,1 e12,1 e11,1 e10,1 e9,1 e8,1 e7,1 e6,1 e5,1 e4,1 e3,1 e2,1 e1,1.0};
   double absvalue=fabs(value);
   int i,decimal=(int)absvalue;
   double real=floor((absvalue-decimal)*1 e18+0.5)-0.5;
   double normalize=fmod(real,1 e3);
   if(normalize>0.0)
     {
      if(normalize>51.5) real+=1 e3-normalize; else real-=normalize;
     }
   double res,last=0.0;
   for(i=0;i<18;i++)
     {
      res=real-fmod(real,digits[i]);
      if(last-res>=0.0) break; else last=res;
     }
   return(i);
  }
//+------------------------------------------------------------------+

未確認ですが、動作するようです

Всё, точка, приплыли! Учимся работать с числами с плавающей точкой и разрабатываем альтернативу с фиксированной точностью десятичной дроби
Всё, точка, приплыли! Учимся работать с числами с плавающей точкой и разрабатываем альтернативу с фиксированной точностью десятичной дроби
  • habr.com
Сегодня мы поговорим о вещественных числах. Точнее, о представлении их процессором при вычислении дробных величин. Каждый из нас сталкивался с выводом в строку чисел вида 3,4999990123 вместо 3,5 или, того хуже, огромной разницей после вычислений между результатом теоретическим и тем, что получилось в результате выполнения программного кода...
 
Igor Makanu:

ハブの記事をもとにhttps://habr.com/company/xakep/blog/257897/

未確認 ですが、動作するようです

もし、0.07という正しい結果が出れば、正しく動作していることになります。

 
Alexey Viktorov:

もし、0.07という正しい結果が出れば、正しく動作していることになります。

が動作しない(((

 
Igor Makanu:

が動作しない(((

そして、どんなアルゴリズムも通用しない...。

 
Alexey Viktorov:

そして、どんなアルゴリズムも通用しない...。

になりますが、問題は与えられた精度で、大きな計算コストの都合で、倍精度の数は、任意の形式で再計算することができます:±符号 - (1 +仮数/252)×2順序- 1023

仮数と次数を抽出するのは簡単ですが、この問題を直接解くのは面白くありません。

 
Igor Makanu:

になりますが、問題は与えられた精度で、大きな計算コストの都合で、倍精度の数は、任意の形式で再計算することができます:±符号 - (1 +仮数/252)×2順序- 1023

仮数と次数を分離するのは簡単だが、この問題を正面から解決するのはおもしろくない

もし、精度が出るのであれば、この件は意味がない。すでに例を挙げましたが、0.07は小数点以下が2桁です。でも、プログラムで桁数を計算しようとすると13桁になってしまう...。しかも0.07は計算結果ではなく、変数を介さずに手入力されている。

 

こんなオプションもあります。

#define  EPSILON   0.000000001
#define  MORE(A,B) ((A)-(B)>EPSILON)

int Digits(double value)
  {
   int digits=0;
   while(MORE(1.0/MathPow(10,digits),value)) 
      digits++;
   return(digits);
  }
 
Mesaoria:

正気に戻ってください。まともに議論するのもナンセンスな話だ。

著者は単にダブル変数の内部構造を完全に誤解しているのです。

О!

 
Alexandr Sokolov:
私はすべてを知っているとは言っていない、何が間違っているのか、あなたのバージョンを見せてください。

プログラム中に定義されているdouble型変数が、それぞれ小数点以下何桁目なのかを知りたい。これはナンセンスだ。double 型の変数はすべて同じ表現になります。Float -浮動小数点として 表現されます。ポイントは左にあることもあれば、右にあることもあり、それは数字の値によって異なります。100万と100万分の1は異なる精度で表現されます。

 
Konstantin Gruzdev:

また、このようなバリエーションもあります。

いいえ、それはうまくいきません、私は昨日タイプ変換でやりました、ここにスクリプトがあります、あなたの例と私の例です。

#define  EPSILON   0.000000001
#define  MORE(A,B) ((A)-(B)>EPSILON)

int Digit(double value)
  {
   int digits=0;
   while(MORE(1.0/MathPow(10,digits),value)) 
      digits++;
   return(digits);
  }
//+------------------------------------------------------------------+
int DoubleToDigits(double value)
 {
   double absvalue=NormalizeDouble(fabs(value-int(value)),15);
   int res=StringLen(string(absvalue))-2;
   return(res<=0?0:res);
 }
//+------------------------------------------------------------------+
void OnStart()
  {
   double f = 122334550.007;
   Print("1. DoubleToDigits() = ",DoubleToDigits(f));
   Print("1. Digit() = ",Digit(f));
   f = 0.007;
   Print("2. DoubleToDigits() = ",DoubleToDigits(f));
   Print("2. Digit() = ",Digit(f));
  }

の結果です。

2018.11.13 01:49:16.131 tst (EURUSD,M30) 1.DoubleToDigits() = 11

2018.11.13 01:49:16.131 tst (EURUSD,M30) 1.デジット() = 0

2018.11.13 01:49:16.131 tst (EURUSD,M30) 2.DoubleToDigits() = 3

2018.11.13 01:49:16.131 tst (EURUSD,M30) 2.デジット() = 3



FP-Printing-PLDI96.pdfで ググれば出てくるが、誰かがアルゴリズム通りにやってくれるとは思えない。