Velocidad de ejecución de las funciones ceil(),round(),floor() - página 6

 
Nikolai Semko:

Ya escribí sobre ello aquí.

ok. como entiendo que estás escribiendo dentro de este terminal y dentro de la precisión dada, no estás interesado en portar y ejecutar el código en cualquier otro dispositivo o plataforma.

Saludos cordiales.

P.D. Un buen programador debe entender que el hardware y el programa pueden cambiar y que hay que evitar errores en el futuro.
 
Andrey Kisselyov:
Si estás escribiendo dentro de los límites del terminal dado y dentro de los límites de su precisión, la portación y el funcionamiento del código en cualquier otro dispositivo o plataforma no te interesa.

Sinceramente.

Exactamente. Estamos hablando de MQL5 (quizás también de MQL4 - no lo he comprobado). Y el código dentro de las clases o algoritmos será perfectamente transferible dentro de MQL. Pero también funcionará en C++. Ya tengo algunos ejemplos.

 
Andrey Kisselyov:

P.D. Un buen programador debe entender que el hardware y el programa pueden cambiar y que es necesario evitar errores en el futuro. Con una tarea como la suya, es posible que no pueda encontrar fácilmente un error en una función que considerará infalible en ese momento.
En esta situación es imposible siquiera imaginar los cambios de los que habla. ¿Qué podría cambiar con las matemáticas para calcular (int)(x+0,5)? ¿Dejará de descartar la parte fraccionaria o qué?
 
Nikolai Semko:
En esta situación, es imposible siquiera imaginar los cambios de los que habla. ¿Qué puede cambiar con las matemáticas de calcular (int)(x+0,5)? ¿Dejará de caer la parte fraccionaria?

Por ejemplo, se introducirá un nuevo tipo de datos...

 
STARIJ:

Por ejemplo, se introducirá un nuevo tipo de datos...

))) Sí, pero el código dejará de funcionar si se anula el tipo de datos antiguo....
 
Me refiero a este lío.
y=(int)(x+0.9999999999999997);

Pongamos un ejemplo:
si cambias incluso el bitness de la máquina, cambias a 64 bits y la precisión de la máquina ha aumentado, tu fórmula dejará de funcionar ya que la precisión de la máquina será muy superior a la que estás poniendo en tu error.

Con respeto.

P.D. puede haber otras opciones en las que su fórmula falle en un rango de números. ajustando constantemente el error por cambiar de máquina, o por cambios en el compilador, de los que no se le informa, o por cambiar la representación de los números en la máquina, o por cortar una parte fraccionaria del número al compilar una nueva versión del terminal... No sabes lo que puede cambiar, y no creo que sea buena idea hacer un IF o sufrir para adivinar lo que va a pasar escribiendo un error una y otra vez...

Creo que hay mucho que pensar.

 
Andrey Kisselyov:

...

P.D. El doble por definición no puede ser un entero, la representación de un número en la memoria de la máquina no cambiará.

¿Quizás estás diciendo que double no es un tipo de dato entero, no que no se puede almacenar un número con valor entero en una variable de tipo double? Un doble entero puede tener un valor entero.

 

Encontré una explicación sencilla de la diferencia entre el redondeo implementado en los ordenadores y el simple truncamiento posterior a la pila. Catorce años, http://delphimaster.net/view/14-10885/all:

Tolik(2003-08-13 11:04) [11].

Este redondeo está aceptado en contabilidad. Así que Hacienda también aplica este redondeo, por lo que todo debería cuadrar, al menos sobre el papel :))



DiamondShark(2003-08-13 11:20) [12]

Oh-ho-ho... Otra vez.
Supongamos que tenemos una distribución de números cercana al azar uniforme. Entonces por redondeo "aritmético" tenemos:

El número Incertidumbre
0 0
1 -1
2 -2
3 -3
4 -4
5 +5
6 +4
7 +3
8 +2
9 +1

Como puede ver fácilmente, si tiene un gran conjunto de números que luego habrá que sumar (totales de partidas de documentos, saldos de cuentas, etc.), el redondeo "aritmético" acumulará un error sistemático con la expectativa
0,5*10^n * 0,1 * N
donde:
n -- peso decimal del dígito al que se redondea (a dos dígitos n=-2, a enteros n=0, etc.)
0,1 es la probabilidad de cada dígito
N es un número de enteros en una matriz

Para igualar las probabilidades de error es necesario compensar el único error no compensado (ver tabla anterior) +5. Esto se hace dividiendo artificialmente en dos igualmente probables +5 -5 dependiendo de la paridad del dígito anterior.

Por cierto, hay una casilla en la palabra de estado de la FPU que controla el modo de redondeo (aritmético/contable).


Fin de la cita.

Otra, http://delphimaster.net/view/15-1340952214/all:"como el usuario medio (gestor/contable) no puede explicar por qué redondear 12,5 y 13,5 - da resultados diferentes".


Cuando se ofrecen al usuario versiones "aceleradas" de las funciones de redondeo hay que advertirle de que dan lugar a un mayor error al sumar. Este error tendrá que ser evaluado cuidadosamente en situaciones muy diferentes. Es peligroso, está cargado de acumulación de errores. Me resulta difícil pensar en un ejemplo en el que el redondeo sea tan importante como para olvidarse de los errores que acumula.

Округление чисел. Неужели ТАК правильно???
  • delphimaster.net
3-10545           Kati                  2003-08-12 10:13  2003.09.04   обновление SQL запроса 14-10898          kalishenko            2003-08-14 20:09  2003.09.04   Win2000 Server и доступ в Интернет 1-10692           lww                   2003-08-20 10:30  2003.09.04   Как написать dll для 1С? 1-10813           koks                  2003-08-20...
 

Andrey Kisselyov:
я говорю про вот это безобразие

y=(int)(x+0.9999999999999997);

Muy bien, señores, ya se han explicado. Voy a cambiar la función de ceil para usted:

y=ceil(x);  ->  y=(x-(int)x>0)?(int)x+1:(int)x;
или через дефайн:
#define _ceil(x) (x-(int)x>0)?(int)x+1:(int)x

Esta variante es entre un 25 y un 50% más lenta que la variante:y=(int)(x+0,99999999999997); pero es máximamente correcta, funciona para enteros negativos y es 3 veces más rápida que ceil(x).

Pero yo, como plebeyo y fracasado, usaré la variante con nueves, porque considero que todos tus argumentos son aburridos y para mí, alguien que lleva mucho tiempo programando en ensamblador, y que por tanto sabe lo que pasa con el código después de la compilación, es demasiado - poner comprobaciones donde se puede prescindir de ellas.

 

Una variante para números positivos y negativos:

#define _ceil(x) (x-(int)x>0)?(int)x+1:(int)x
#define _round(x) (x>0)?(int)(x+0.5):(int)(x-0.5)
#define _floor(x) (x>0)?(int)x:((int)x-x>0)?(int)x-1:(int)x
Esto parece ser un reemplazo completo de ceil(),round(),floor(), que da una ventaja de velocidad de 3-4 veces.