Implementaciones alternativas de funciones/enfoques estándar - página 10

 
pavlick_:
)). Esto puede tener un lugar sólo en la artesanía personal con el conocimiento exacto de la gama de valores, pero no en la biblioteca std. Las funciones incorporadas no están escritas por tontos, no te creas el más listo. Aquí hay un amigo que también escribe un comportamiento indefinido y no especificado y luego se sorprende de que no funcione así https://www.linux.org.ru/forum/development/14422428#comments. Todo este ahorro de varios nanosegundos ni siquiera será visible en el algoritmo real (no en el bucle desnudo).

Sólo que ahora me he puesto al día con lo que decías.
Retiro lo de que no estás al tanto. Me disculpo.
Sí, puedes utilizar esa variante con la condición de que el número doble esté en el rango de -9007199254740992 a 9007199254740992 (2 a la potencia de 53 (número de bits en la mantisa))

 
Renat Fatkhullin:
Piensa en lo que obtendrás fuera del rango de los números enteros.

¿Qué te parece esto?

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);}

resultado:

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 ... Прервите скрипт, когда надоест ждать

la prueba parece mostrar una identidad completa.

Sin embargo, la velocidad de la solución alternativa en este caso, en el que hay una comprobación de rango, es mayor en unas 2 veces (en lugar de 3-8), pero esto es si el número doble está en el rangode -9007199254740992 a 9007199254740992. Pero es mucho más alto cuando está fuera de este rango.

Archivos adjuntos:
TestRound.mq5  9 kb
 
Nikolai Semko:


la prueba parece mostrar una identidad completa.

Sin embargo, esta variante no tiene en cuenta el desbordamiento de la variable de entradade tipo doble, cuando toma los valores nan, snan.

Si hay que tenerlo en cuenta, se puede añadir una comprobación más, pero aun así esta variante funcionará más rápido que la función original

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:

Redactar un EA para un probador/optimizador. Ahí es donde la velocidad en la práctica es importante.

 
fxsaber:

Redactar un EA para un probador/optimizador. Ahí es donde la velocidad es importante en la práctica.

Como muchos saben, también hago gráficos suaves. Las funciones de redondeo se utilizan activamente para suavizar los gráficos y trabajar con cada píxel.

Antes no podía ni imaginar que la función de redondeo fuera más lenta que la extracción de la raíz cuadrada del doble.
Es por esta razón por la que me he acostumbrado a ahogar esos nanosegundos. Porque esos nanosegundos en el gráfico suavizado pueden convertirse en milisegundos en cada fotograma, y un fotograma puede cambiar cada 33 milisegundos.

 
Nikolai Semko:

Como muchos saben, también me ocupo de los gráficos con antialiasing. Las funciones de redondeo se utilizan activamente para los gráficos con antialiasing y para trabajar con cada píxel.
Por eso me he dedicado a suavizar esos nanosegundos. Porque esos nanosegundos en los gráficos suavizados pueden convertirse en milisegundos en cada fotograma, y un fotograma puede cambiar cada 33 milisegundos.

Por supuesto, esto es importante para los gráficos. Por eso, desde hace mucho tiempo existen optimizaciones algorítmicas para casi todas las tareas comunes.

 
fxsaber:

Por supuesto, esto es importante para los gráficos. Por eso, desde hace mucho tiempo existen optimizaciones algorítmicas para casi todas las tareas comunes.

Se equivoca. El campo allí todavía no está arado, y lo que está arado está cerrado. Y en MQL aún más. La clase CCanvas está muy lejos de la optimización y casi no hay antialiasing y lo que hay de antialiasing es insatisfactorio.

 

¿Por qué no utiliza LONG_MAX/MIN? De alguna manera quedaría más bonito. Se ve bien, creo. He ejecutado tus pruebas con gcc (con una mínima modificación, claro, compilador muy antiguo 5.4.0, lo que tenía a mano):

1. Compilación con -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. Compilación con -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

Su código tiene un problema con el cálculo del tiempo - salida en milisegundos (no nano), y todavía no entiendo por qué necesita menos t0.

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

No es así. Todavía hay un campo sin arar, y lo que está arado está cerrado.

Me refería a la experiencia mundial. Mira los algoritmos en los foros temáticos donde hacen demostraciones de gráficos. La gente está compartiendo sus algoritmos rápidos.

 
fxsaber:

Me refería a la experiencia mundial. Busque los algoritmos en los foros temáticos donde se hacen demostraciones de gráficos. La gente está compartiendo algoritmos rápidos.

¿Puede enviarme el enlace, por favor?