标准功能/方法的其他实现方式 - 页 10

 
pavlick_:
)).这可能只在对数值范围有确切了解的个人工艺品中才有用武之地,但在std库中则没有。内置函数不是傻瓜写的,不要以为你是最聪明的。这里有一个朋友,他也写了未定义和未指定的行为,然后惊讶地发现它并不是这样的https://www.linux.org.ru/forum/development/14422428#comments。 所有这些节省的几纳秒甚至在实际算法中都看不到(不是在裸奔中)。

现在我才明白你在说什么。
我把它收回来,你不在这个圈子里。我表示歉意。
是的,你可以使用这个变体,但有一个条件,即双数位于-9007199254740992到9007199254740992的范围内(2到53的幂(尾数的位数))。

 
Renat Fatkhullin:
想想在整数范围之外你会得到什么。

这个怎么样?

double Ceil (double x) { return double((x>9007199254740992 || x<-9007199254740992 )?x:(x-(long)x>0)?(long)x+1:(long)x);}
double Round(double x) { return double((x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)(x+0.5):(long)(x-0.5));}
double Floor(double x) { return double((x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)x:((long)x-x>0)?(long)x-1:(long)x);}

结果。

2018.08.26 10:49:23.552 TestRound (Crypto.ALT,M10)      Время цикла без округления = 1.317 наносекунд, сумма = 115583114403605978808320.00000000
2018.08.26 10:49:23.556 TestRound (Crypto.ALT,M10)      Время выполнения функции ceil =  2.129 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.557 TestRound (Crypto.ALT,M10)      Время выполнения функции Ceil =  0.100 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.560 TestRound (Crypto.ALT,M10)      Время выполнения функции floor = 1.299 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.561 TestRound (Crypto.ALT,M10)      Время выполнения функции Floor = 0.120 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.564 TestRound (Crypto.ALT,M10)      Время выполнения функции round = 1.787 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.566 TestRound (Crypto.ALT,M10)      Время выполнения функции Round = 0.106 наносекунд, Контрольная сумма = 1.15583114403606 e+23
2018.08.26 10:49:23.566 TestRound (Crypto.ALT,M10)      Идет бесконечный поиск расхождения по случайным числам double ... Прервите скрипт, когда надоест ждать

该测试似乎显示了完全的一致性。

然而,在这种情况下,有范围检查的替代方案的速度要高2倍左右(而不是3-8倍),但这是在数字双倍在-9007199254740992到9007199254740992 之间的情况下。但是当它在这个范围之外时,它就会高得多。

附加的文件:
TestRound.mq5  9 kb
 
Nikolai Semko:


该测试似乎显示了完全的一致性。

然而,这个变体没有考虑到双倍类型 的输入变量的溢出,当它取值nan, snan时。

如果必须考虑到这一点,你可以多加一个检查,但这个变体仍然会比原始函数工作得更快。

double Ceil (double x) { return double((!MathIsValidNumber(x) || x>9007199254740992 || x<-9007199254740992 )?x:(x-(long)x>0)?(long)x+1:(long)x);}
double Round(double x) { return double((!MathIsValidNumber(x) || x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)(x+0.5):(long)(x-0.5));}
double Floor(double x) { return double((!MathIsValidNumber(x) || x>9007199254740992 || x<-9007199254740992 )?x:(x>0)?(long)x:((long)x-x>0)?(long)x-1:(long)x);}
 
Nikolai Semko:

为测试员/优化员写一个EA。这就是实践中速度的重要性所在。

 
fxsaber:

为测试员/优化员写一个EA。这就是速度在实践中的重要性。

很多人都知道,我也做流畅的图形。四舍五入函数正是为平滑图形和处理每个像素而积极使用的。

早些时候,我甚至无法想象四舍五入功能比提取双倍的平方根还要慢。
正是由于这个原因,我已经采取了掐断这些纳秒的做法。因为平滑图上的那些纳秒可以变成每一帧的毫秒,而一帧可以每33毫秒变化一次。

 
Nikolai Semko:

正如许多人所知,我也处理抗锯齿的图形。四舍五入函数正是为抗锯齿图形和处理每个像素而积极使用的。
正是由于这个原因,我从事了平滑这些纳秒的工作。因为平滑图形上的那些纳秒可以变成每一帧的毫秒,而一帧可以每33毫秒变化一次。

当然,这对图形很重要。这就是为什么几乎所有常见任务的算法优化在那里已经存在了很长时间。

 
fxsaber:

当然,这对图形很重要。这就是为什么几乎所有常见任务的算法优化在那里已经存在了很长时间。

你错了。在MQL中更是如此。CCanvas类离 最佳状态很远,几乎没有抗锯齿,而现有的抗锯齿也不令人满意。

 

你为什么不使用LONG_MAX/MIN?这在某种程度上会看起来更漂亮。我想,它看起来不错。我用gcc运行了你的测试(当然,经过最小的修改,非常老的编译器5.4.0,我手头的东西)。

1.用-O3进行编译。

Время цикла без округления = 0.001099185 секунд, сумма = 1.15583114 e+23
Время выполнения функции ceil =  0.004310106 секунд, сумма = 1.15583114 e+23
Время выполнения функции Ceil =  0.001912712 секунд, сумма = 1.15583114 e+23
Время выполнения функции floor =  0.005283493 секунд, сумма = 1.15583114 e+23
Время выполнения функции Floor =  0.002031304 секунд, сумма = 1.15583114 e+23
Время выполнения функции round =  0.005308409 секунд, сумма = 1.15583114 e+23
Время выполнения функции Round =  0.002344382 секунд, сумма = 1.15583114 e+23

2.用-Ofast进行编译

Время цикла без округления = 0.000552652 секунд, сумма = 1.15583114 e+23
Время выполнения функции ceil =  0.001720999 секунд, сумма = 1.15583114 e+23
Время выполнения функции Ceil =  0.00189282 секунд, сумма = 1.15583114 e+23
Время выполнения функции floor =  0.001430063 секунд, сумма = 1.15583114 e+23
Время выполнения функции Floor =  0.001979336 секунд, сумма = 1.15583114 e+23
Время выполнения функции round =  0.001698521 секунд, сумма = 1.15583114 e+23
Время выполнения функции Round =  0.001944874 секунд, сумма = 1.15583114 e+23

你的代码在时间计算上有问题--输出的单位是毫秒(而不是纳米),而且我还是不明白为什么你需要减去t0。

Print("Время выполнения функции ceil =  "+DoubleToString((double)(GetMicrosecondCount()-t-t0)/1000,3)+" наносекунд, Контрольная сумма = "+string(s));
 
Nikolai Semko:

错了。还有一块未耕种的田地,已耕种的则是封闭的。

我说的是世界经验。看看专题论坛上的算法,他们在那里做图形演示。人们正在分享他们的快速算法。

 
fxsaber:

我说的是世界经验。在制作图形演示的专题论坛上寻找算法。人们正在分享快速算法。

请把链接发给我。