Альтернативные реализации стандартных функций/подходов - страница 10

 
pavlick_:
)). Этому может быть место только в личных поделках при точном знании диапазона значений, но никак не в стд библиотеке. Штатные функции не дураками писаны, не думайте, что самый умный. Вот тоже товарищ пишет на undefined и unspecified behavior, а пототм удивляется, что работает не так https://www.linux.org.ru/forum/development/14422428#comments. А вся эта экономия в несколько наносекунд в реальном алгоритме (а не в голом цикле) даже видна не будет.

Только сейчас догнал о том, что Вы говорили. 
Беру свои слова обратно о том, что Вы не в теме. Прошу прощения.
Да, тот вариант можно использовать с оговоркой, что число double лежит в диапазоне от -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.15583114403606e+23
2018.08.26 10:49:23.557 TestRound (Crypto.ALT,M10)      Время выполнения функции Ceil =  0.100 наносекунд, Контрольная сумма = 1.15583114403606e+23
2018.08.26 10:49:23.560 TestRound (Crypto.ALT,M10)      Время выполнения функции floor = 1.299 наносекунд, Контрольная сумма = 1.15583114403606e+23
2018.08.26 10:49:23.561 TestRound (Crypto.ALT,M10)      Время выполнения функции Floor = 0.120 наносекунд, Контрольная сумма = 1.15583114403606e+23
2018.08.26 10:49:23.564 TestRound (Crypto.ALT,M10)      Время выполнения функции round = 1.787 наносекунд, Контрольная сумма = 1.15583114403606e+23
2018.08.26 10:49:23.566 TestRound (Crypto.ALT,M10)      Время выполнения функции Round = 0.106 наносекунд, Контрольная сумма = 1.15583114403606e+23
2018.08.26 10:49:23.566 TestRound (Crypto.ALT,M10)      Идет бесконечный поиск расхождения по случайным числам double ... Прервите скрипт, когда надоест ждать

вроде тест показывает полную идентичность.

Правда скорость альтернативного решения в таком варианте, где идет проверка диапазона, выше примерно всего в 2 раза (а не 3-8), но это если число double находится в диапазоне от -9007199254740992 до 9007199254740992. Зато значительно выше, когда находится вне этого диапазона.

Файлы:
TestRound.mq5  9 kb
 
Nikolai Semko:


вроде тест показывает полную идентичность.

Правда такой вариант не учитывает переполнения входной переменной типа double, когда она принимает значения 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:

Запилите советник для тестера/оптимизатора. Именно там важна скорость на практике.

 
fxsaber:

Запилите советник для тестера/оптимизатора. Именно там важна скорость на практике.

Как многим известно, я так же занимаюсь сглаженной графикой. Именно для сглаженной графики и работе с каждым пикселем активно используются функции округления. 

Я раньше даже представить себе не мог, что функция округления выполняется медленнее извлечения квадратного корня из числа double.
Именно по этой причине я занялся выдушиванием этих наносекунд. Потому как эти наносекунды на сглаженной графике могут превращаться в миллисекунды на каждом кадре, а кадр может меняться каждые 33 миллисекунды.

 
Nikolai Semko:

Как многим известно, я так же занимаюсь сглаженной графикой. Именно для сглаженной графики и работе с каждым пикселем активно используются функции округления. 
Именно по этой причине я занялся выдушиванием этих наносекунд. Потому как эти наносекунды на сглаженной графике могут превращаться в миллисекунды на каждом кадре, а кадр может меняться каждые 33 миллисекунды.

Безусловно, для графики это важно. Поэтому там очень давно существуют алгоритмические оптимизации почти на все распространенные задачи.

 
fxsaber:

Безусловно, для графики это важно. Поэтому там очень давно существуют алгоритмические оптимизации почти на все распространенные задачи.

Ошибаетесь. Там еще не паханное поле, а что распахано, то закрыто.  А у MQL тем более.  Класс CCanvas очень далек от оптимальности, а сглаженность там практически отсутствует, а то что есть из сглаженности - неудовлетворительно. 

 

А почему не пользуетесь LONG_MAX/MIN ? Будет как-то приличней смотреться. Вроде, ничего выглядит. Я прогал ваши тесты на gcc (c мин модификацией, естественно, компилятор очень старый 5.4.0, что было под рукой):

1. Компиляция с -O3

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

2. Компиляция с -Ofast

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

У вас в коде подсчёт времени барахлит - вывод в милисекундах (а не нано), и я так и не понял - зачем нужно минус t0.

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

Ошибаетесь. Там еще не паханное поле, а что распахано, то закрыто.

Про мировой опыт говорил. Посмотрите алгоритмы на тематических форумах, где граф. демки делают. Народ делится быстрыми алгоритмами.

 
fxsaber:

Про мировой опыт говорил. Посмотрите алгоритмы на тематических форумах, где граф. демки делают. Народ делится быстрыми алгоритмами.

Сбросьте ссылочку пожалуйста 
Причина обращения: