Me he encontrado con este lenguaje de programación recientemente:
const float Zero = 0.0;
que luego se usa en las comparaciones:
if (x > Zero) {..}
¿Alguien puede explicar si esto es realmente más eficiente, legible o mantenible que:
if (x > 0.0) {..}
NOTA: Puedo pensar en otras razones para definir esta constante, solo me pregunto sobre su uso en este contexto.
x
tiene tipofloat
, entoncesx > 0.0
fuerza la promoción adouble
, que podría ser menos eficiente. Sin embargo, esa no es una buena razón para usar una constante con nombre, solo para asegurarse de que sus constantes tengan el tipo correcto (por ejemplo0f
,float(0)
odecltype(x)(0)
).13.37
no esfloat
, esdouble
. Entonces, si querías unfloat
, es concebible que tu tutor fuera correcto. En algunos contextos (p. Ej., La asignación a un flotante)13.37
se convertirá implícitamente alfloat
que deseaba, y en otros contextos (p. Ej., Deducción de tipo de plantilla) no lo será, mientras questatic const float
siempre comienza como el tipo que deseaba. Por lo tanto, más seguro de tipo. Eso sí, así sería13.37f
! Sin embargo, hay otras razones para evitar la macro que la "seguridad de tipo", por lo que es muy probable que el tutor le haya dado un argumento pobre.Respuestas:
Los posibles motivos son el almacenamiento en caché, el nombre o el tipo de forzamiento
Almacenamiento en caché (no aplicable)
Desea evitar el costo de crear un objeto durante el acto de comparación. En Java, un ejemplo sería
Esto implica un proceso de creación bastante pesado y se sirve mejor utilizando el método estático proporcionado:
Esto permite comparaciones sin incurrir en un costo repetido de creación, ya que la JVM almacena en caché previamente el BigDecimal durante la inicialización.
En el caso de lo que ha descrito, un primitivo está realizando el mismo trabajo. Esto es en gran medida redundante en términos de almacenamiento en caché y rendimiento.
Nombramiento (poco probable)
El desarrollador original está intentando proporcionar una convención de nomenclatura uniforme para valores comunes en todo el sistema. Esto tiene algún mérito, especialmente con valores poco comunes, pero algo tan básico como cero solo vale la pena en el caso del caso de almacenamiento en caché anterior.
Tipo de forzamiento (lo más probable)
El desarrollador original está intentando forzar un tipo primitivo particular para garantizar que las comparaciones se emitan a su tipo correcto y posiblemente a una escala particular (número de lugares decimales). Esto está bien, pero el nombre simple "cero" probablemente sea un detalle insuficiente para este caso de uso con ZERO_1DP como una expresión más apropiada de la intención.
fuente
typedef
mantendrían el tipo de variable exactamente en un lugar y permitirían cambiarlo sin tener que alterar el código.0.0f
.byteVar1 = byteVar2 Or CB128
parece un poco mejor quebyteVar1 = byteVar2 Or CByte(128)
. Por supuesto, tener un sufijo numérico apropiado para bytes sería aún mejor. Dado que C # promueve los operandos de bit a bit para los operadores,int
incluso cuando se garantice que el resultado encajará en abyte
, el problema no es tan relevante allí.Es por "molestar a las herramientas"
Una posible razón que no veo en la lista aquí es porque muchas herramientas de calidad señalan el uso de números mágicos . A menudo es una mala práctica tener números mágicos en un algoritmo sin hacerlos claramente visibles para un cambio posterior, especialmente si están duplicados en varios lugares del código.
Por lo tanto, si bien estas herramientas tienen razón al señalar estos problemas, a menudo generan falsos positivos para situaciones en las que estos valores son inofensivos y es más probable que sean estáticos o simplemente sean valores de inicialización.
Y cuando eso sucede, a veces te enfrentas a la elección de:
Sobre rendimiento
Depende del lenguaje, supongo, pero esto es bastante común en Java y no tiene ningún impacto en el rendimiento, ya que los valores están en línea en el momento de la compilación si son constantes reales
static final
. No tendría un impacto en C o C ++ si se declaran como constantes o incluso como macros de preprocesador.fuente
Esto puede tener sentido ya que define explícitamente
Zero
que es de tipofloat
.Al menos en C y C ++, el valor
0.0
es de tipodouble
, mientras que el equivalentefloat
es0.0f
. Por lo tanto, asumirx
que comparas también es siempre unfloat
dichomientras que en realidad promueve
x
paradouble
que coincida con el tipo de lo0.0
que podría conducir a problemas (especialmente con pruebas de igualdad) La comparación sin conversión sería, por supuesto,que hace lo mismo que
Sin embargo, creo que sería mucho más útil habilitar advertencias de conversiones en el compilador en lugar de hacer que los usuarios escriban código incómodo.
fuente
En primer lugar, aquí cero se define como
float
, noint
. Por supuesto, esto no afecta nada en la comparación, pero en otros casos cuando se usa esta constante, puede hacer la diferencia.No veo otra razón por la cual
Zero
se declara una constante aquí. Es solo un estilo de codificación, y es mejor seguir el estilo si se usa en cualquier otro lugar de ese programa.fuente
Es casi seguro que sea exactamente eficiente durante la ejecución (a menos que su compilador sea muy primitivo) y muy ligeramente menos eficiente durante la compilación.
En cuanto a si eso es más legible que
x > 0
... recuerde que hay personas que honestamente, genuinamente, piensan que COBOL fue una gran idea y un placer trabajar con ellos, y luego hay personas que piensan exactamente lo mismo sobre C. (El rumor ha ¡es que incluso existen algunos programadores con la misma opinión sobre C ++!) En otras palabras, no vas a llegar a un acuerdo general sobre este punto, y probablemente no valga la pena pelear.fuente
Si estaba escribiendo código genérico (es decir, no específico del tipo), entonces muy posiblemente. Una
zero()
función podría aplicarse a cualquier tipo algebraico, o cualquier tipo que sea una adición de grupo wrt. Podría ser un número entero, podría ser un valor de coma flotante, incluso podría ser una función si su variable es, por ejemplo, una función dentro de un espacio lineal (por ejemplo, x es una función lineal de la forma z -> a_x * z + b_x) y luegozero()
proporciona la función con a y b siendo amboszero()
del tipo subyacente.Por lo tanto, esperaría dicho código en, por ejemplo, C ++ posiblemente (aunque a
zero()
no es muy común AFAIK), o en Julia, y tal vez en otros idiomas.fuente