Математическое округление. - страница 3

 
Dmitry Fedoseev:
А какая быстрая? Та ваша что ли? Вам же Слава отвечал про ограниченность аргумента у нее.
Быстрой не знаю, но быстрее написать не сложно. Напомните по аргументам Славы.
 
fxsaber:
Быстрой не знаю, но быстрее написать не сложно. Напомните по аргументам Славы.
#include <Math\Stat\Math.mqh>

#define HALF_PLUS (0.5 + DBL_EPSILON)

double MathRound( const double Value, const uint digits )
{
  static const double Points[] = {1.0e+0, 1.0e+1, 1.0e+2, 1.0e+3, 1.0e+4, 1.0e+5, 1.0e+6, 1.0e+7, 1.0e+8, 1.0e+9, 1.0e+10, 1.0e+11, 1.0e+12, 1.0e+13, 1.0e+14, 1.0e+15, 1.0e+16};
  const double point = (digits > 16) ? 1.0e+16 : Points[digits];
  const long Integer = (long)Value; // чтобы не создавать крайне медленный относительный epsilon

  return((long)((Value > 0) ? (Value - Integer) * point + HALF_PLUS : (Value - Integer) * point - HALF_PLUS) / point + Integer);
}

void Compare( const double Num )
{
  Print(Num);
  
  for (int digits = 0; digits < 16; digits++)
    if (MathRound(Num, digits) - MathRound(Num, (uint)digits) != 0)
    {      
      Print(digits, ": ", MathRound(Num, digits));
      Print(digits, ": ", MathRound(Num, (uint)digits));
    }
}

void OnStart()
{
  for (int i = 0; i < 100; i++)
  {
    Compare((double)MathRand() / +SHORT_MAX);
    Compare((double)MathRand() / -SHORT_MAX);
  }
}
 
Vitalie Postolache:

А там и думать нечего, достаточно немного переделать скрипт и убедиться, что результат один и тот же, когда округление до 8 знака, больше - начинаются различия:

Про 8 знаков есть упоминание в документации, но и при меньшем числе разрядов результат Math::MathRound может отличаться от ::NormalizeDouble

 
A100:

Про 8 знаков есть упоминание в документации, но и при меньшем числе разрядов результат Math::MathRound может отличаться от ::NormalizeDouble

Проверил - нет различий.
 
fxsaber:
Быстрой не знаю, но быстрее написать не сложно. Напомните по аргументам Славы.
Может не Слава, не помню, но кто-то из МК. 
 
Dmitry Fedoseev:
Может не Слава, не помню, но кто-то из МК. 
Выше скрипт, там полное совпадение наблюдается.
 
fxsaber:
#define HALF_PLUS (0.5 + DBL_EPSILON)

  static const double Points[] = {1.0e+0, 1.0e+1, 1.0e+2, 1.0e+3, 1.0e+4, 1.0e+5, 1.0e+6, 1.0e+7, 1.0e+8, 1.0e+9, 1.0e+10, 1.0e+11, 1.0e+12, 1.0e+13, 1.0e+14, 1.0e+15, 1.0e+16};

e- заменили на e+ ... логично... а зачем DBL_EPSILON?

 
fxsaber:
Выше скрипт, там полное совпадение наблюдается.
Замечательно!
 
A100:

e- заменили на e+ ... логично... а зачем DBL_EPSILON?

Помню только, что была причина. Возможно, рудимент уже.
 
fxsaber:
Проверил - нет различий
#include <Math\Stat\Math.mqh>
void OnStart()
{
        const double d = 5.4555;
        int digits = 3;
        Print( d, "->", MathRound( d, digits ), "->", ::NormalizeDouble( d, digits ));
}
Результат: 5.4555->5.455->5.456
Причина обращения: