价格!=价格?

 

我试图理解我所看到的一些奇怪的东西,这样我就可以在将来更好地用代码来处理它......

我注意到我的一个指标发生了一些奇怪的事情,它没有做它应该做的事情,所以我检查了代码,它看起来很正确。 所以我做了一点调查,最后创建了一个小的测试指标

基本上这似乎是真的。

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

......你知道这是怎么发生的吗?

 
以前的问题和回答
 
RaptorUK:

....知道这是怎么发生的吗?

这是由NormalizeDouble()的内部工作原理决定的。比如说...

   double TestValue = 1.57373;
   if (TestValue != NormalizeDouble(TestValue, 5)) MessageBox("WTF?");

顺便说一下,如果你做了以下的事情,结果也一样。

   double TestValue = StrToDouble("1.57373");
   if (TestValue != NormalizeDouble(TestValue, 5)) MessageBox("WTF?");

在初始分配后,TestValue = 1.5737300000000001。NormalizeDouble(..., 5)产生1.57372999999999。

 
WHRoeder:
以前的问题和回答
恕我直言,我认为那个帖子没有回答我在这个主题中的问题。
我知道除了NormalizeDouble,还有其他的方法......我不明白的是为什么iClose要返回一个没有被Normalize的值。
 
jjc:

这是由NormalizeDouble()的内部工作原理决定的。例如...

顺便说一下,如果你做以下事情,结果也一样。

在初始分配后,TestValue = 1.5737300000000001。NormalizeDouble(..., 5)产生1.57372999999999。


那么,我如何让TestValue等于1.57373而不是>或<?
 
RaptorUK:

那么,我如何让TestValue等于1.57373而不是>或<?
如果这一点还不清楚的话,1.57373不能精确地表示为一个浮点。像0.1这样的数值也是如此。唯一奇怪的是,NormalizeDouble()最终使用了与MQ4语言的其他部分不同的近似值。
 
jjc:
如果这一点还不清楚的话,1.57373不能准确地表示为一个浮点值。像 0.1这样的数值也是如此。唯一奇怪的是,NormalizeDouble()最终使用了与MQ4语言的其他部分不同的近似值。

啊......不,这不清楚......我不知道这一点。 谢谢,我会调查的。
 
RaptorUK:
啊......不,这不清楚,我不知道。 谢谢,我会调查的。

浮点值和算术的速度很快,因为计算机的处理器中就有对它们的支持,但也有一个代价,那就是有些值不能在浮点变量中精确表示。(关于速度影响的例子,见https://www.mql5.com/en/forum/116228/page2#156859)

实际上,任何涉及双数的东西都会引入一种四舍五入的错误。这导致了各种有趣的怪异现象。例如,0.1*10=1.0,但0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1!= 1.0。

这样做的结果是NormalizeDouble(x, y)与Round(x, y)并不完全同义。NormalizeDouble()返回最接近于四舍五入的浮点值。如果你做NormalizeDouble(a, n) == NormalizeDouble(b, n),那么你基本上是在说 "考虑到浮点运算可能在小数点后n位以上引入舍入差异,a和b是否相等?"。

正如许多人所说,NormalizeDouble(a, 5) == NormalizeDouble(b, 5) 因此实际上等同于MathAbs(a - b) < 0.00001,而且后者的执行速度略快。后者也很常见,因为它被广泛用于那些没有提供与NormalizeDouble()函数等价物的语言/平台。但性能上的差异是如此之小,如果你觉得NormalizeDouble()能使你的代码更易读,我还是坚持使用。

所有这些对于有双倍数据类型的语言来说是完全正常的。引入一些专有的和典型的MQ4怪癖的地方是1.57373 != NormalizeDouble(1.57373, 5)。声明常数1.57373和使用NormalizeDouble()会选择不同的最佳浮点近似值,这是不正常的。

 

谢谢你。 :-)

我知道这个问题,但不太清楚原因,因此没有完全意识到可能的影响。

 
除零外,从不比较双数是否相等
if (a > b)
if (a - b > Point / 2.)
if (a >= b)
if (a - b > -Point)
if (a != b)
if (MathAbs(a - b) > Point / 2.)
 
WHRoeder:
除了零之外,永远不要比较双数是否相等


我有一百多行代码正是这样做的......而且几乎对所有看到的东西都使用了NormalizeDouble 来使其可靠地工作。 我理解你的建议背后的想法,谢谢你,但我认为它们可能会对我的代码的可读性产生负面影响,从而影响将来的修改。

我将在不远的将来修改这段代码,以使它能在它所运行的图表的时间框架之外的其他时间框架上工作。 当我要这样做的时候,我打算消除NormalizeDoubles,用其他东西来代替......还不是100%确定,也许在比较之前转换为整数。

谢谢你的帮助,像往常一样 :-)