Получаем количество десятичных знаков после запятой любых чисел (не только котировок) в обход Digits() на MQL4 и MQL5 - страница 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]={1e17,1e16,1e15,1e14,1e13,1e12,1e11,1e10,1e9,1e8,1e7,1e6,1e5,1e4,1e3,1e2,1e1,1.0};
   double absvalue=fabs(value);
   int i,decimal=(int)absvalue;
   double real=floor((absvalue-decimal)*1e18+0.5)-0.5;
   double normalize=fmod(real,1e3);
   if(normalize>0.0)
     {
      if(normalize>51.5) real+=1e3-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 имеет два знака после запятой. Но, если попытаться программно посчитать количество знаков, получим штук тринадцать... И 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:

Опомнитесь. Это бред, который даже не следует обсуждать всерьез. 

У автора просто тотальное непонимание внутреннего устройства double-переменных.

О! 

 
Alexandr Sokolov:
Я не утверждал что всё знаю, лучше скажите в чём ошибка или покажите свой вариант

Вы хотите знать, сколько знаков после запятой определены у каждой переменной типа double в Вашей программе. Это и есть бред. Все переменные типа double имеют одинаковое представление. Представлены они в формате Float - с плавающей точкой. Иногда точка левее, иногда правее - зависит от значения числа. Один миллион и одна миллионная представляются с разной точностью. 

 
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. Digit() = 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. Digit() = 3



можно нагуглить FP-Printing-PLDI96.pdf , но сомневаюсь, что кто то сделает все по алгоритму

Причина обращения: