错误、漏洞、问题 - 页 2822 1...281528162817281828192820282128222823282428252826282728282829...3184 新评论 Alexey Navoykov 2020.08.10 17:46 #28211 Nikolai Semko: 只有四舍五入没有使用标准的round(), ceil(), floor(),因为它们也是返回双数。但通过这些,特别是它们比普通的工作更快。 它可能更快,但它就是错的。将12345.0000000000001之类的东西传入你的ceil(与你的例子类似),你可以在输出中得到12346。 Nikolai Semko 2020.08.10 18:05 #28212 Alexey Navoykov: 它可能会更快,但它就是错的。 将12345.0000000000001这样的东西(与你的例子类似)传入你的ceil,你可以在输出中得到12346。 你自己试过吗? 试试吧。Print(ceil( 12345.0000000000001)); Print(Ceil( 12345.0000000000001)); Print(ceil( 12345.000000000001)); Print(Ceil( 12345.000000000001));输出。2020.08.10 12:03:23.856 ErrorNormalizeDouble (EURUSD,M1) 12345.0 2020.08.10 12:03:23.856 ErrorNormalizeDouble (EURUSD,M1) 12345 2020.08.10 12:03:23.856 ErrorNormalizeDouble (EURUSD,M1) 12346.0 2020.08.10 12:03:23.856 ErrorNormalizeDouble (EURUSD,M1) 12346 应该是12346,因为它是一个ceil("从上面返回最接近的整数数字值"),第一种情况是12345,因为双倍型的有效数字是17,而你有18 fxsaber 2020.08.10 18:23 #28213 Nikolai Semko: 真的,你不能比较双打。这只是一个硬性规定。 当然,有可能,有时甚至有必要将双胞胎直接相互比较。 例如,在优化过程中,OnTick有时会被调用一万亿次。为了了解是否执行一个待定限价,内置的测试器会比较当前对应的符号价格和限价。它在每次调用OnTick前对每个挂单进行处理。也就是说,这些检查要做几百、几千亿次。 而且每次都是通过规范化来完成。嗯,这是一种可怕的计算资源 浪费。由于挂单的价格和符号被初步规范化。因此,它们可以而且应该直接相互比较。 MQL-定制的MQL测试器在性能上很容易胜过本地内置的测试器。 Nikolai Semko 2020.08.10 18:56 #28214 fxsaber:当然,有可能,有时甚至有必要将双胞胎直接相互比较。例如,在优化过程中,OnTick有时会被调用一万亿次。内置的测试器,为了了解是否执行一个待定的限制,比较当前对应的符号价格和限制价格。它在每次调用OnTick前对每个挂单进行处理。也就是说,这些检查要做几百、几千亿次。而且每次都是通过规范化来完成。嗯,这是一种可怕的计算资源 浪费。由于挂单的价格和符号被初步规范化。因此,它们可以而且应该直接相互比较。MQL-定制的MQL测试器在性能上很容易胜过本地内置的测试器。NormalizeDouble()是一个非常昂贵的函数。因此,你最好忘记它。这里有一个脚本,演示了NormalizeDouble()和normalize with int之间的区别。#define SIZE 1000000 int Ceil (double x) {return (x-(int)x>0)?(int)x+1:(int)x;} int Round(double x) {return (x>0)?(int)(x+0.5):(int)(x-0.5);} int Floor(double x) {return (x>0)?(int)x:((int)x-x>0)?(int)x-1:(int)x;} //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { double a[SIZE]; double s1=0,s2=0, s3=0; for (int i=0;i<SIZE;i++) a[i]=(rand()-16384)/M_PI; ulong t1=GetMicrosecondCount(); for (int i=0;i<SIZE;i++) s1+=a[i]; t1=GetMicrosecondCount()-t1; ulong t2=GetMicrosecondCount(); for (int i=0;i<SIZE;i++) s2+=NormalizeDouble(a[i],5); t2=GetMicrosecondCount()-t2; ulong t3=GetMicrosecondCount(); for (int i=0;i<SIZE;i++) s3+=Round(a[i]*100000); s3/=100000; t3=GetMicrosecondCount()-t3; Print("простая сумма - " + string(t1)+ " микросекунд, сумма = "+ DoubleToString(s1,18)); Print("сумма с NormalizeDouble - " + string(t2)+ " микросекунд, сумма = "+ DoubleToString(s2,18)); Print("сумма, нормализированная через int - " + string(t3)+ " микросекунд, сумма = "+ DoubleToString(s3,18)); }结果。2020.08.10 12:55:30.766 TestSpeedNormalizeDouble (USDCAD,H4) простая сумма - 1394 микросекунд, сумма = 626010.5038610587362201 2020.08.10 12:55:30.766 TestSpeedNormalizeDouble (USDCAD,H4) сумма с NormalizeDouble - 5363 микросекунд, сумма = 626010.5046099 795727060 2020.08.10 12:55:30.766 TestSpeedNormalizeDouble (USDCAD,H4) сумма, нормализированная через int - 1733 микросекунд, сумма = 626010.5046099999 453873 SZZ的归一化也更准确(你可以通过归一化的最后一位数字后的9的数量看到它--用蓝色突出显示)。 Nikolai Semko 2020.08.10 19:17 #28215 Nikolai Semko:NormalizeDouble()是一个非常昂贵的函数。这就是为什么最好是忘记它。这里有一个脚本,演示了NormalizeDouble()和Normalize with int之间的区别。结果。 SZZ通过int进行的归一化甚至更准确(你可以通过归一化最后一位数字后的9的数量看出这一点--用蓝色突出显示)。 如果不是通过双数,而是通过长数求和,那么结果会更令人印象深刻,因为通过int求和(乘法和四舍五入,然后除以最终的总和)的计算速度比正常的双数求和快。 #define SIZE 1000000 int Ceil (double x) {return (x-(int)x>0)?(int)x+1:(int)x;} int Round(double x) {return (x>0)?(int)(x+0.5):(int)(x-0.5);} int Floor(double x) {return (x>0)?(int)x:((int)x-x>0)?(int)x-1:(int)x;} //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() { double a[SIZE]; double s1=0,s2=0, s3=0; long s=0; for (int i=0;i<SIZE;i++) a[i]=(rand()-16384)/M_PI; ulong t1=GetMicrosecondCount(); for (int i=0;i<SIZE;i++) s1+=a[i]; t1=GetMicrosecondCount()-t1; ulong t2=GetMicrosecondCount(); for (int i=0;i<SIZE;i++) s2+=NormalizeDouble(a[i],5); t2=GetMicrosecondCount()-t2; ulong t3=GetMicrosecondCount(); for (int i=0;i<SIZE;i++) s+=Round(a[i]*100000); s3=s/100000.0; t3=GetMicrosecondCount()-t3; Print("простая сумма - " + string(t1)+ " микросекунд, сумма = "+ DoubleToString(s1,18)); Print("сумма с NormalizeDouble - " + string(t2)+ " микросекунд, сумма = "+ DoubleToString(s2,18)); Print("сумма, нормализированная через int - " + string(t3)+ " микросекунд, сумма = "+ DoubleToString(s3,18)); } 结果。 2020.08.10 13:15:58.982 TestSpeedNormalizeDouble (USDCAD,H4) простая сумма - 1408 микросекунд, сумма = 460384.3207830497995019 2020.08.10 13:15:58.982 TestSpeedNormalizeDouble (USDCAD,H4) сумма с NormalizeDouble - 6277 микросекунд, сумма = 460384.3162300114054233 2020.08.10 13:15:58.982 TestSpeedNormalizeDouble (USDCAD,H4) сумма, нормализированная через int - 964 микросекунд, сумма = 460384.3162299999967218 Rorschach 2020.08.10 19:36 #28216 Nikolai Semko:如果求和不是通过double,而是通过long,那么结果会更令人印象深刻,因为通过int求和(乘法和四舍五入,然后再除以总和)比普通的double求和更快。结果。 小数 ,用于比较添加。 链接错了,这不是一个完整的实现。 Alexey Navoykov 2020.08.10 19:38 #28217 fxsaber:而且每次都是通过正常化来完成。嗯,这是对计算资源 的严重浪费。 你怎么知道的? 因为即使价格没有被规范化,检查也只是在没有任何规范化的情况下进行。 if (fabs(price-limitprice) < ticksize/2) 鉴于价格是ticksize的倍数 Alexey Navoykov 2020.08.10 20:07 #28218 Nikolai Semko: 此外,通过int进行的归一化也被证明是更准确的(你可以通过归一化的最后一个数字后的9的数量看到它--用蓝色突出显示)。 这个测试是不正确的。 为什么你只在最后 除以100000.0一次? 应该在每次迭代时进行,然后求和。 这是一个公平的比较。 但这根本不是归一化 - 你只是优化了你的测试算法。自然,它将更快、更准确(因为累积误差减少了)。 fxsaber 2020.08.10 20:13 #28219 Alexey Navoykov:你怎么知道这些? 因为你可以向测试仪输入非正常化的价格,它将以相同的方式处理它们。 毕竟,即使价格没有规范化,在没有任何规范化的情况下,检查也很容易完成。 在这种情况下,我指的是一个单一的标准算法,应用它之后,你可以直接比较这个标准的双打。 所以测试者并不直接比较双打。它是通过NormalizeDouble、ticksize或其他东西来实现的。但肯定不是通过直接比较双打。而且这一点也不理性。 Nikolai Semko 2020.08.10 20:23 #28220 fxsaber:当然,有可能,有时甚至有必要将双胞胎直接相互比较。例如,Optimize OnTick有时会被调用一万亿次。内置的测试器,为了了解是否执行悬挂的限制,对当前对应的符号价格和限制价格进行比较。它在每次调用OnTick前对每个挂单进行处理。也就是说,这些检查要做几百、几千亿次。而且每次都是通过规范化来完成。嗯,这是一种可怕的计算资源 浪费。由于挂单的价格和符号被初步规范化。因此,它们可以而且应该直接相互比较。MQL-定制的MQL测试器在性能上不比本地内置的测试器差。 所以我决定检查一下性能的无稽之谈版本。 结果令人惊讶。,即使是预规范化的双倍数比较,也比通过epsilon或转换为int的双倍数比较时平均速度更慢。 #define SIZE 1000000 int Ceil (double x) {return (x-(int)x>0)?(int)x+1:(int)x;} int Round(double x) {return (x>0)?(int)(x+0.5):(int)(x-0.5);} int Floor(double x) {return (x>0)?(int)x:((int)x-x>0)?(int)x-1:(int)x;} bool is_equal(double d1, double d2, double e=0.000000001) {return fabs(d1-d2)<e;} void OnStart() { double a[SIZE], a_norm[SIZE]; int s1=0,s2=0, s3=0; for (int i=0;i<SIZE;i++) { a[i]=(rand()-16384)/1641.1452; a_norm[i]=NormalizeDouble(a[i],2); } double test = 1.11; ulong t1=GetMicrosecondCount(); for (int i=0;i<SIZE;i++) if (a_norm[i]==test) s1++; t1=GetMicrosecondCount()-t1; ulong t2=GetMicrosecondCount(); for (int i=0;i<SIZE;i++) if (is_equal(a[i],test,0.005)) s2++; t2=GetMicrosecondCount()-t2; ulong t3=GetMicrosecondCount(); int test_int = test*100; for (int i=0;i<SIZE;i++) if (Round(a[i]*100)==test_int) s3++; t3=GetMicrosecondCount()-t3; Print("простое сравнение предварительно нормализированых double - " + string(t1)+ " микросекунд, всего совпадений = "+ string(s1)); Print("сравнение double через эпсилон - " + string(t2)+ " микросекунд, всего совпадений = "+ string(s2)); Print("сравнение double через преобразование в int - " + string(t3)+ " микросекунд, всего совпадений = "+ string(s3)); } 其结果是。 2020.08.10 14:31:39.620 TestCompareDouble (USDCAD,H4) простое сравнение предварительно нормализированых double - 900 микросекунд, всего совпадений = 486 2020.08.10 14:31:39.620 TestCompareDouble (USDCAD,H4) сравнение double через эпсилон - 723 микросекунд, всего совпадений = 486 2020.08.10 14:31:39.620 TestCompareDouble (USDCAD,H4) сравнение double через преобразование в int - 805 микросекунд, всего совпадений = 486 2020.08.10 14:31:42.607 TestCompareDouble (USDCAD,H4) простое сравнение предварительно нормализированых double - 1533 микросекунд, всего совпадений = 488 2020.08.10 14:31:42.607 TestCompareDouble (USDCAD,H4) сравнение double через эпсилон - 758 микросекунд, всего совпадений = 488 2020.08.10 14:31:42.607 TestCompareDouble (USDCAD,H4) сравнение double через преобразование в int - 790 микросекунд, всего совпадений = 488 2020.08.10 14:31:44.638 TestCompareDouble (USDCAD,H4) простое сравнение предварительно нормализированых double - 986 микросекунд, всего совпадений = 472 2020.08.10 14:31:44.638 TestCompareDouble (USDCAD,H4) сравнение double через эпсилон - 722 микросекунд, всего совпадений = 472 2020.08.10 14:31:44.638 TestCompareDouble (USDCAD,H4) сравнение double через преобразование в int - 834 микросекунд, всего совпадений = 472 我不排除这在很大程度上取决于处理器的新颖性和结构,对某人来说,结果可能是不同的。 告诉你真相--我甚至不明白为什么会发生这种情况。,似乎编译器对随机数之和没有任何优化。你不能把四舍五入放在括号外。 似乎处理器中的双倍数比较是一个命令 当通过epsilon(最快的方式)进行比较时,我们仍然有一个两个双倍数的比较操作,但此外我们还有一个传递三个参数的函数调用和一个减法操作。 两个双数的比较操作的性能是否取决于变量本身的值?我怀疑这一点。 天啊,我不明白。请帮助我,我有什么地方没有考虑到,或者我哪里做错了? 1...281528162817281828192820282128222823282428252826282728282829...3184 新评论 您错过了交易机会: 免费交易应用程序 8,000+信号可供复制 探索金融市场的经济新闻 注册 登录 拉丁字符(不带空格) 密码将被发送至该邮箱 发生错误 使用 Google 登录 您同意网站政策和使用条款 如果您没有帐号,请注册 可以使用cookies登录MQL5.com网站。 请在您的浏览器中启用必要的设置,否则您将无法登录。 忘记您的登录名/密码? 使用 Google 登录
只有四舍五入没有使用标准的round(), ceil(), floor(),因为它们也是返回双数。
但通过这些,特别是它们比普通的工作更快。
它可能会更快,但它就是错的。
你自己试过吗?
试试吧。
输出。
应该是12346,因为它是一个ceil("从上面返回最接近的整数数字值"),第一种情况是12345,因为双倍型的有效数字是17,而你有18
真的,你不能比较双打。这只是一个硬性规定。
当然,有可能,有时甚至有必要将双胞胎直接相互比较。
例如,在优化过程中,OnTick有时会被调用一万亿次。为了了解是否执行一个待定限价,内置的测试器会比较当前对应的符号价格和限价。它在每次调用OnTick前对每个挂单进行处理。也就是说,这些检查要做几百、几千亿次。
而且每次都是通过规范化来完成。嗯,这是一种可怕的计算资源 浪费。由于挂单的价格和符号被初步规范化。因此,它们可以而且应该直接相互比较。
MQL-定制的MQL测试器在性能上很容易胜过本地内置的测试器。
fxsaber:
当然,有可能,有时甚至有必要将双胞胎直接相互比较。
例如,在优化过程中,OnTick有时会被调用一万亿次。内置的测试器,为了了解是否执行一个待定的限制,比较当前对应的符号价格和限制价格。它在每次调用OnTick前对每个挂单进行处理。也就是说,这些检查要做几百、几千亿次。
而且每次都是通过规范化来完成。嗯,这是一种可怕的计算资源 浪费。由于挂单的价格和符号被初步规范化。因此,它们可以而且应该直接相互比较。
MQL-定制的MQL测试器在性能上很容易胜过本地内置的测试器。
NormalizeDouble()是一个非常昂贵的函数。因此,你最好忘记它。
这里有一个脚本,演示了NormalizeDouble()和normalize with int之间的区别。
结果。
SZZ的归一化也更准确(你可以通过归一化的最后一位数字后的9的数量看到它--用蓝色突出显示)。NormalizeDouble()是一个非常昂贵的函数。这就是为什么最好是忘记它。
这里有一个脚本,演示了NormalizeDouble()和Normalize with int之间的区别。
结果。
SZZ通过int进行的归一化甚至更准确(你可以通过归一化最后一位数字后的9的数量看出这一点--用蓝色突出显示)。如果不是通过双数,而是通过长数求和,那么结果会更令人印象深刻,因为通过int求和(乘法和四舍五入,然后除以最终的总和)的计算速度比正常的双数求和快。
结果。
如果求和不是通过double,而是通过long,那么结果会更令人印象深刻,因为通过int求和(乘法和四舍五入,然后再除以总和)比普通的double求和更快。
结果。
小数 ,用于比较添加。
链接错了,这不是一个完整的实现。
而且每次都是通过正常化来完成。嗯,这是对计算资源 的严重浪费。
你怎么知道的? 因为即使价格没有被规范化,检查也只是在没有任何规范化的情况下进行。
鉴于价格是ticksize的倍数
此外,通过int进行的归一化也被证明是更准确的(你可以通过归一化的最后一个数字后的9的数量看到它--用蓝色突出显示)。
这个测试是不正确的。 为什么你只在最后 除以100000.0一次? 应该在每次迭代时进行,然后求和。 这是一个公平的比较。 但这根本不是归一化 - 你只是优化了你的测试算法。自然,它将更快、更准确(因为累积误差减少了)。
你怎么知道这些?
因为你可以向测试仪输入非正常化的价格,它将以相同的方式处理它们。
毕竟,即使价格没有规范化,在没有任何规范化的情况下,检查也很容易完成。
在这种情况下,我指的是一个单一的标准算法,应用它之后,你可以直接比较这个标准的双打。
所以测试者并不直接比较双打。它是通过NormalizeDouble、ticksize或其他东西来实现的。但肯定不是通过直接比较双打。而且这一点也不理性。
当然,有可能,有时甚至有必要将双胞胎直接相互比较。
例如,Optimize OnTick有时会被调用一万亿次。内置的测试器,为了了解是否执行悬挂的限制,对当前对应的符号价格和限制价格进行比较。它在每次调用OnTick前对每个挂单进行处理。也就是说,这些检查要做几百、几千亿次。
而且每次都是通过规范化来完成。嗯,这是一种可怕的计算资源 浪费。由于挂单的价格和符号被初步规范化。因此,它们可以而且应该直接相互比较。
MQL-定制的MQL测试器在性能上不比本地内置的测试器差。
所以我决定检查一下性能的无稽之谈版本。
结果令人惊讶。
,即使是预规范化的双倍数比较,也比通过epsilon或转换为int的双倍数比较时平均速度更慢。
其结果是。
我不排除这在很大程度上取决于处理器的新颖性和结构,对某人来说,结果可能是不同的。
告诉你真相--我甚至不明白为什么会发生这种情况。
,似乎编译器对随机数之和没有任何优化。你不能把四舍五入放在括号外。
似乎处理器中的双倍数比较是一个命令
当通过epsilon(最快的方式)进行比较时,我们仍然有一个两个双倍数的比较操作,但此外我们还有一个传递三个参数的函数调用和一个减法操作。
两个双数的比较操作的性能是否取决于变量本身的值?我怀疑这一点。
天啊,我不明白。请帮助我,我有什么地方没有考虑到,或者我哪里做错了?