向MQL4大师们提问。还是关于双倍比较。 - 页 5

 

惊人的结论!如果你甚至根本不 "理解 "什么是数字,你怎么会对任何数字有这种想法?

 
Integer:

惊人的结论!如果你甚至根本不 "理解 "什么是数字,你怎么会对任何数字有这种想法?

你开始挑剔文字了吗?很明显,这将是一场人格暗杀。:)
我应该马上说,我宁愿不参与这样的解释,因为如果你对案情没有什么可说的,为什么还要说话?
 
VBAG:
我想感谢所有专家的见解!

Irtron, 我选择了你的变体,我非常喜欢它。我针对一般情况稍加修正,并进行了检查。

int ComparePrice(double a, double b, double digit)
{
a -= b。
b = 数字。
如果(a>b)
返回(1)。
如果(a < -b)
返回(-1)。
返回(0)。
}
谢谢。
我忘了澄清,我想把任何预定义的值传入数字。
double digit14=0.00000000000001;
双位数12=0.000000000001。
双位数8=0.00000001。
双位数4=0.0001。
double digit2=0.01。
这将决定所需的精度。
对于这种功能,它的工作速度非常快。
Irtron, 再次感谢。

 
Irtron:
整数

惊人的结论!如果你甚至根本不 "理解 "什么是数字,你怎么会对任何数字有这种想法?

开始挑剔话语了?很明显,从这里开始,它将变得个人化。:)
我应该马上说,我宁愿不参与这样的解释,因为如果你对案情没有什么可说的,为什么还要说话?


为什么要挑剔,我只是读了你写的东西。 你的理解显然受到了 "你公然的...(你说说看)"

VBAG,既然有一个函数NormalizeDouble()可以比ComparePrice()更快地比较两个数字,为什么还要重新发明车轮呢?

 
Integer:

VBAG,既然有一个NormalizeDouble()函数可以比ComparePrice()更快地比较两个数字,为什么还要重新发明车轮呢?

该函数比较两个双数,并给出答案<,>或=到小数点后14位(NormalizeDouble()限制在8位)。
如果你能建议类似的自行车或更好的替代解决方案,我将很乐意使用它们。
恭敬地说。
弗拉基米尔
 
VBAG:
整数

VBAG,既然有一个NormalizeDouble()函数可以比ComparePrice()更快地比较两个数字,为什么还要重新发明车轮呢?

该函数比较两个双数,并给出答案<,>或=到小数点后14位(NormalizeDouble()限制在8位)。
如果你能建议一个类似的轮子或更好的替代品,我很乐意使用它们。
恭敬地说。
弗拉基米尔
下面是对我的兴趣的一个测试。
int start()
  {
//----
    double a = 1.23450001, b = 1.23449999;
 
    int start1 = GetTickCount(), c1;
    for ( c1 = 0; c1 < 100000000; c1 ++ ) CD( a, b,0.00000001);
    int end1 = GetTickCount();
    
 
    int start2 = GetTickCount(), c2;
    for ( c2 = 0; c2 < 100000000; c2 ++ )   xNormalize(a,b,8);
    int end2 = GetTickCount();
 
    Print( "CD: ", (end1-start1), ", xNormalize: ", (end2-start2) );
 
    return(0);
   }
 
//+ CompareDouble ---------------------------------------------------+ CompareDouble
int CD(double a, double b, double digit)
{
    a -= b;
    b = digit;
    if (a > b)
        return (1);
    if (a < -b)
        return (-1);
    return (0);
}
 
// Две операции NormalizeDouble----
bool xNormalize(double a, double b,int digit)
  {
   double d1 = NormalizeDouble(a,digit);
   double d2 = NormalizeDouble(b,digit);
   
//   bool bCompare=d2-d1 > 0.0;
   bool bCompare= 0;
   return(bCompare);
2007.09.12 07:15:09 $CheckCompareDouble USDJPY,M5: CD: 20485, xNormalize: 51265

结论。
CD函数比较两个双数,给出小数点后14位的答案<, >或=,并且比简单执行NormalizeDouble()快2倍(即使没有逻辑比较)。
 
是的,两次调用NormalizeDouble()的时间比CD长,而一次调用则更快。14位数字的精确度是一个很好的点缀 :-)
 
我最近也一直在尝试比较真实的数字!

许多人写道,为了进行比较,必须使用内置函数NormalizeDouble()。(这也是开发人员的建议)。
因此,我想首先定义一下。"什么是NormalizeDouble()?",也就是说,它是如何工作的,它的算法是什么。

MQL4参考 - 数据转换 - NormalizeDouble

将一个浮点数舍入到指定的精度。
...

我不知道在MQL4中是如何组织四舍五入的(问开发人员),但我知道一个标准的方法 将浮点数舍入到指定的精度。
在这里,一个函数。

double MyNormalizeDouble(double value, int digits)
{
    int factor = MathRound( MathPow(10, digits) ); // factor - это множитель,
                                                      с помощью которого мы из VALUE сделаем целое число
    double result = MathRound(factor * value) / factor;
    
    return(result);
}
从这个函数你可以看到,我们首先从一个实数变成一个整数,然后再回到一个实数。
为了进行比较,只需要去找一个整数就可以了。

因此,我认为比较实数的最快和最可靠的方法是将它们转换为整数。
这就是对比结果的模样。

double a;
double b;
int factor = MathRound( MathPow(10, digits) ); // digits - это точность с которой будем сравнивать
                                                           Если сравниваем цены, то это предопределенная переменная Digits
...

if (MathRound( (а - b) * factor )  !=  0)
{
    ... // a != b
}

if (MathRound( (а - b) * factor )  ==  0)
{
    ... // a == b
}

if (MathRound( (а - b) * factor )  >  0)
{
    ... // a > b
}

if (MathRound( (а - b) * factor )  <  0)
{
    ... // a < b
}

所有这些都可以被格式化为一个函数并使用。写起来很麻烦,似乎很清楚如何做一个函数!
我认为这种方式比调用NormalizeDouble()更快。

为了安全起见,你也可以让MathRound()函数返回一个整数,因为默认情况下它会返回双数。
最简单的方法是这样做的

int MyMathRound(double value)
{
    int result = MathRound(value);
    return(result);
}
那么只有整数会被比较,而且比较得很好!


我认为这种方式是最正确的,你认为呢?
 
gravity001:

所以我认为最快速和最可靠的方法是将实数转换成整数
比较结果将是这样的。

double a;
double b;
int factor = MathRound( MathPow(10, digits) ); // digits - это точность с которой будем сравнивать
                                                           Если сравниваем цены, то это предопределенная переменная Digits
...

if (MathRound( (а - b) * factor )  !=  0)
{
    ... // a != b
}

if (MathRound( (а - b) * factor )  ==  0)
{
    ... // a == b
}

if (MathRound( (а - b) * factor )  >  0)
{
    ... // a > b
}

if (MathRound( (а - b) * factor )  <  0)
{
    ... // a < b
}

我认为这才是正确的做法,不是吗?

我不这么认为。自己判断。
Irtron 代码的全部优点在于它的紧凑性(绝对没有多余的东西--甚至变量也被保存了!)。
而你建议我们至少应该为每一个
(а - b)
操作增加两个操作。
(MathRound( (а - b) * factor ) 
这是一个速度上的优势!
 
VBAG:
我不这么认为。自己判断

是的,稍微慢一点。
int start()
{
    double a, b;
    int start1, start2, end, c;
    
    a = 1.23450001;
    b = 1.23449999;
    
    start1 = GetTickCount();
    
    for (c = 100000000; c > 0; c--)
        ComparePrice(a, b,0.0001);
    
    start2 = GetTickCount();
    
    for (c = 100000000; c > 0; c--)
        intCompare(a, b,10000);
    
    end = GetTickCount();
 
    Print("ComparePrice: ", start2 - start1, ", intCompare: ", end - start2);
 
    return(0);
}
 
int ComparePrice(double a, double b, double point)
{
    a -= b;
    b = point / 2.;
    if (a > b)
        return (1);
    if (a < -b)
        return (-1);
    return (0);
}
 
int intCompare(double a, double b, int factor)
{
    return(MathRound( (a-b) * factor ));
}
比较价格:32032, intCompare:35296