价格!=价格? - 页 7

 

WHRoeder: 这个代码好吗(特别是检查"添加 "和 "默认")?它也可以作为那些访问这个主题并只翻到最后一页的人的一个简单的最终参考(就像我一样)。

#define LT    0
#define GT    1
#define GTE   2
#define LTE   3
#define EQ    4
#define NEQ   5

bool doublecomp(double a,int type,double b){
  // See https://forum.mql4.com/45053/page4
  // 0 compare doesn't need this function
  switch(type){
    case LT: return(b-a>Point/2.);
    case GT: return(a-b>Point/2.);
    case GTE: return(a-b>-Point); // Added
    case LTE: return(b-a>-Point); // Added
    case EQ: return(!(MathAbs(a-b)>Point/2.));
    case NEQ: return(MathAbs(a-b)>Point/2.);
    default: return(-1); // Added - needed to avoid compile error about not all control paths returning a value
  }
}
 

这段代码是不准确的。

if( !MathAbs( a - b ) > Point/2)如何用于比较是否相等?那会告诉你1.4999 == 1.5000

 
SDC: 如何用if( !MathAbs( a - b ) > Point/2)来比较是否相等?这将 告诉你1.4999 == 1.5000
  1. 它不是的
    if( ! (MathAbs( a     -  b    ) > Point/2) ) be used to compare for equality? That would tell you 1.4999 == 1.5000
    if( ! (MathAbs(1.4999 - 1.5000  > 0.00005  )
    if( ! (0.0001                   > 0.00005  )
    if( ! (true                                )
    if( false                                  ) 1.4999 is NOT equal to 1.5000
  2. 而我曾在PM中向Roel13 指出,GEQ/LEQ必须是-Point/2,但他没有编辑帖子
  3. 正如我之前发布的,只有在平等/不平等很重要的情况下,你才需要担心这种无稽之谈。如果你想在一根蜡烛的高点之上开盘,如果(由于四舍五入)它可能正好在高点上触发,这有什么关系吗?如果没有,就用bid > high[]
 

我使用

if(NormalizeDouble(price1-price2,Digits)==0)


或者对于不是实际价格的双倍数,更高的精度

if(NormalizeDouble(value1-value2,8)==0)
 
SDC: 我使用
if(NormalizeDouble(price1-price2,Digits)==0)
阅读 第一个 帖子,你就会知道为什么这不是一个好主意。
 

猛龙队关于这个代码的帖子

double TestValue = iClose(NULL, 0, 0);
   
if(TestValue != NormalizeDouble(TestValue, Digits) ) //not equal

所以,如果你使用。

double TestValue = iClose(NULL, 0, 0);

if(NormalizeDouble(TestValue - iClose(NULL,0,0),Digits)==0) // they are considered equal

我以各种方式测试了该方法,我还没有发现它不能返回预期或期望的结果的情况。
 

最终代码...谢谢WHRoeder

#define LT    0
#define GT    1
#define GTE   2
#define LTE   3
#define EQ    4
#define NEQ   5

bool ComparePrice(double a,int type,double b){
  // See https://forum.mql4.com/45053/page4
  // 0 compare doesn't need this function
  switch(type){
    case LT: return(b-a>Point/2.);
    case GT: return(a-b>Point/2.);
    case GTE: return(a-b>-Point/2.);
    case LTE: return(b-a>-Point/2.);
    case EQ: return(!(MathAbs(a-b)>Point/2.));
    case NEQ: return(MathAbs(a-b)>Point/2.);
  }
  return(-1);
}


还有,也许有一个辅助功能,用于比较所有其他不是价格的双数......

bool CompareNormal(double a,int type,double b){
  // With thanks https://forum.mql4.com/45053/page4
  // 0 compare doesn't need this function
  switch(type){
    case LT: return(b-a>0.0000000000000000000000000000001);
    case GT: return(a-b>0.0000000000000000000000000000001);
    case LTE: return(b-a>-0.0000000000000000000000000000001);
    case GTE: return(a-b>-0.0000000000000000000000000000001);
    case EQ: return(!(MathAbs(a-b)>0.0000000000000000000000000000001));
    case NEQ: return(MathAbs(a-b)>0.0000000000000000000000000000001);
  }
  return(-1);
}


请参阅 "MQL4参考 > 语言基础 > 数据类型 > 实数类型(double, float)"中关于使用小数字进行比较的内容。

也许有人知道如何在expon中更好地书写0.00...1。

 
Roel13: 也许有人知道如何用expon写0.00...1更好。
// case LT: return(b-a>0.0000000000000000000000000000001);
// case LT: return(b-a>1.0e-30);
参见实数类型(double, float) - MQL4文档
注意在上面的例子中,epsilon的值不能小于预定义的常数DBL_EPSILON。这个常数的值是2.2204460492503131e-016。
同样,这些都不是必要的,除了在等价/不等价 很重要的情况下。例如,在前一个高点之上开盘,由于四舍五入,你不希望在高点开盘。
 

所以我发现了一些其他有趣的东西,可能与"//0比较不需要这个函数"有关。

也许这只是最新版本中的一个错误,不确定。与0比较的功能不再正常了。我不得不求助于一些不友好的东西,比如。

outcome=(int(outcome*100)/100.0); //解决2位数问题

只是为了确保0值实际上是作为0值结束的。

WHRoeder,谢谢。需要更多的研究 :)

 

我认为这个话题涉及到太多不必要的复杂性。

试着让你的程序员的生活尽可能的简单。在那些你需要进行双倍数比较的类中编写定义(或者如果你真的必须这样做的话,就使用方法)。

// add more floating point zeros if you need a higher precision
#define  isZero(x) (fabs(x) < 0.000000001)
#define  isEqual(x,y) (fabs(x-y) < 0.000000001)

当你需要比较两个双数时,在这样的条件下使用它。

if (isEqual(myFirstDouble, mySecondDouble))
{
  // first and second doubles are considered equal
  // do something
}

如果你想看一个双数是否为零(或非常非常接近于零),就用这样的条件。

if (isZero(myDouble))
{
  // myDouble is considered zero
  // do something
}


顺便说一句,因为我看到很多帖子都在谈论除法。

有了封装,我们往往会忘记 "外包给 "一些实用方法的代码的成本。提醒自己,划分在计算上是非常昂贵的! 特别是,一旦被包裹在实用类的某个地方的漂亮实用方法中,我们就开始在指标或EA中到处使用它们,并且早已忘记它们执行的计算步骤。在使用策略测试器时,我们为自己的粗心大意付出了很多不必要的时间。

经验法则。加法和减法要比乘法和除法快得多。除法运算花费的计算时间最多。 尽可能地优化除法运算!如果分母是固定的,比如在这个循环中...

for(int i=0; i < rates_total; i++)
{
    // ...
    double fraction = someNumeratorValue / 100;
    // ...
}

那么就用它的反转值1/x替换分母x

for(int i=0; i < rates_total; i++)
{
    // ...
    double fraction = 0.01 * someNumeratorValue; // replace a denominator with it's inverted value, if possible.
    // ...
}

另外,如果除法的结果总是一样的,那么就做一次计算,并将结果保存在一个变量中,这样你就可以在代码中的任何地方使用它(例如在循环中)。

double tradesPerDay = totalTradesPerYear/365;

for(int i=0; i < rates_total; i++)
{
    // use precomputed tradesPerDay rather than computing the division here.
}

干杯。

A.T.