....知道这是怎么发生的吗?
这是由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。
这是由NormalizeDouble()的内部工作原理决定的。例如...
顺便说一下,如果你做以下事情,结果也一样。
在初始分配后,TestValue = 1.5737300000000001。NormalizeDouble(..., 5)产生1.57372999999999。
那么,我如何让TestValue等于1.57373而不是>或<?
如果这一点还不清楚的话,1.57373不能准确地表示为一个浮点值。像 0.1这样的数值也是如此。唯一奇怪的是,NormalizeDouble()最终使用了与MQ4语言的其他部分不同的近似值。
啊......不,这不清楚......我不知道这一点。 谢谢,我会调查的。
啊......不,这不清楚,我不知道。 谢谢,我会调查的。
浮点值和算术的速度很快,因为计算机的处理器中就有对它们的支持,但也有一个代价,那就是有些值不能在浮点变量中精确表示。(关于速度影响的例子,见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.) |
除了零之外,永远不要比较双数是否相等
我有一百多行代码正是这样做的......而且几乎对所有看到的东西都使用了NormalizeDouble 来使其可靠地工作。 我理解你的建议背后的想法,谢谢你,但我认为它们可能会对我的代码的可读性产生负面影响,从而影响将来的修改。
我将在不远的将来修改这段代码,以使它能在它所运行的图表的时间框架之外的其他时间框架上工作。 当我要这样做的时候,我打算消除NormalizeDoubles,用其他东西来代替......还不是100%确定,也许在比较之前转换为整数。
谢谢你的帮助,像往常一样 :-)
我试图理解我所看到的一些奇怪的东西,这样我就可以在将来更好地用代码来处理它......
我注意到我的一个指标发生了一些奇怪的事情,它没有做它应该做的事情,所以我检查了代码,它看起来很正确。 所以我做了一点调查,最后创建了一个小的测试指标。
基本上这似乎是真的。
......你知道这是怎么发生的吗?