Функция расчета лота от размера депозита. - страница 3

 
Alexey Oreshkin:
ну и что. Мы говорим о разных вещах. Приведённая мною функция считает количество знаков после запятой, а не кратность одного числа другому.

Ваша функция правильно работает только со значениями типа 0.1, 0.01 и т.д. Такой результат можно получить без цикла, через логарифм.

Задача определить число знаком после запятой у любого числа. 

 
Dmitry Fedoseev:

Ваша функция правильно работает только со значениями типа 0.1, 0.01 и т.д. Такой результат можно получить без цикла, через логарифм.

Задача определить число знаком после запятой у любого числа. 

Заинтриговал прям. Пойду проверю.

 

функция не моя, не проверял :)

int foo(float f, int level = 0)
{
    if (level > FLT_DIG) {
        return FLT_DIG;
    }
    if (f < 0) {
        return foo(-f);
    }
    if (f < 1) {
        return foo(f + 1);
    }
    f -= round(f);
    if (fabs(f) <= FLT_EPSILON) {
        return level;
    }
    return foo(f * 10, level + 1); 

} 

 
Event:

функция не моя, не проверял :)

} 

Ну ничего себе, вот это завернуто.
 
Dmitry Fedoseev:
Ну ничего себе, вот это завернуто.

знак числа - учитывается

максимальное кол-во знаков - учитывается 

эпсилон - учитывается

должна работать ? 

 
Event:

знак числа - учитывается

максимальное кол-во знаков - учитывается 

эпсилон - учитывается

должна работать ? 

Должна, но не работает. Отдаю 0.1, получаю 0.
 
Dmitry Fedoseev:

Ваша функция правильно работает только со значениями типа 0.1, 0.01 и т.д. Такой результат можно получить без цикла, через логарифм.

Задача определить число знаком после запятой у любого числа. 

Точно, эта функция не со всеми числами работает. Печаль :(
Пойду думать как сделать функцию для любого числа.
 

В Code Base у меня есть вариант функции, определяющей количество десятичных знаков после запятой (количество знаков в дробной части).

При необходимости можно и на её основе что-то делать.


А это набросала сейчас пример из "на коленке" (функция из Code Base взята "как есть"):

//+------------------------------------------------------------------+
//|                                                         test.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//---
#define TEST_PRINT_TWO(x,y)   Print(__LINE__,", ",__FUNCTION__,", ",(#x)," = ",(x),", ",(#y)," = ",(y))
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   string symbol=Symbol();
//---
   double lotstep=MarketInfo(symbol,MODE_LOTSTEP); // шаг изменения размера лота
   int count=GetQuantDigits(lotstep);
//---
   TEST_PRINT_TWO(DoubleToString(lotstep),IntegerToString(count));
  }
//+------------------------------------------------------------------+
//|GetQuantDigits - функция для определения количества дробных чисел |
//|(количество десятичных знаков)                                    |
//+------------------------------------------------------------------+
//|2015, Dina Paches (последнее изменение 25.09.2015)                |
//+------------------------------------------------------------------+
int GetQuantDigits(const double val,//число типа double
                   const int digits=8)
  {
   int res=digits;
   if(res<1 || res>8)
     {
      Print(__LINE__,__FUNCTION__," Error code. digits <1 or >8.");
      res=-1;
      return(res);
     }
//---если число = 0, то выходим
   if(NormalizeDouble(val,digits)==0)
     {
      res=0;
      return(res);
     }
//---
   double val_abs=val;
   double val_floor=0;
//---если число < 0, сделаем его для расчётов положительным
   if(NormalizeDouble(val_abs,digits)<0)
     {val_abs=MathAbs(val_abs);}
//---выделим из числа целое значение
   val_floor=MathFloor(val_abs);
//---выделим из числа значения после десятичной точки
   val_abs=NormalizeDouble(val_abs-val_floor,digits);
//---если после десятичной точки нули, то выходим
   if(NormalizeDouble(val_abs,digits)==0)
     {
      res=0;
      return(res);
     }
//---если дошли сюда, значит есть цифры кроме 0 после десятичной точки.
//---преобразуем числа после десятичного знака в целое число
   int val_pow=(int)MathPow(10,digits);
   int val_res_dig=(int)(NormalizeDouble(val_abs*val_pow,0));
//---а теперь преобразуем это целое число в текст
   string text=IntegerToString(val_res_dig);
//---определим длину полученного текста
   int lengh=StringLen(text);
//---определим количество десятичных знаков
   for(int i=lengh-1;i>=0;i--)
     {
      if(StringFind(text,"0",i)==i)
        {res=res-1;}
      else {return(res);}
     }
//---
   return(res);
  }
//+------------------------------------------------------------------+

Записи в журнале "Эксперты":


 

И вот ещё один вариант.

int fun(double ch)
{
 int i = 0;
 double res = 0, ostatok = fmod(ch, 1);
 while(ostatok != 0 && i < 16) // число взято от фонаря для прерывания зацикленности
  {
   res = ostatok * 10;
   ostatok = NormalizeDouble(fmod(res, 1), 8); // Вроде 8 максимально
   i++;
  }
 return(i);
}/*******************************************************************/

Не долго проверялось, но вроде работает.

 

Dmitry Fedoseev:
Должна, но не работает. Отдаю 0.1, получаю 0.

Функция написана на С

На mql5 действительно выдает 0.

А на C# выдает 1.

Может mql кривой?

 

 

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace test {

        [TestClass]
        public class TstDeg{
                const int DBL_DIG = 16;
                const double DBL_EPSILON = Double.Epsilon;

                [TestMethod]
                public void TestMethod1() {
                        double a = 0.1;
                        int deg = foo(a);
                }

                int foo(double f, int level = 0) {
                        if (level > DBL_DIG) {
                                return DBL_DIG;
                        }
                        if (f < 0) {
                                return foo(-f);
                        }
                        if (f < 1) {
                                return foo(f + 1);
                        }
                        f -= Math.Round(f);
                        if (Math.Abs(f) <= DBL_EPSILON) {
                                return level;
                        }
                        return foo(f * 10, level + 1);
                }
        }
}