En los idiomas que no permiten guiones bajos en literales enteros , ¿es una buena idea crear una constante por mil millones? Por ejemplo, en C ++:
size_t ONE_BILLION = 1000000000;
Ciertamente, no deberíamos crear constantes para números pequeños como 100. Pero con 9 ceros, podría decirse que es fácil dejar un cero o agregar uno adicional en un código como este:
tv_sec = timeInNanosec / 1000000000;
tv_nsec = timeInNanosec % 1000000000;
coding-style
Martin C. Martin
fuente
fuente
1e9
,10^9
o1_000_000_000
si el idioma que está usando lo admite.Respuestas:
La mayoría de los idiomas presentan algún tipo de notación exponencial. Un millón es
1e6
, (lo que significa 1 por 10 a la potencia de 6). Esto básicamente resuelve el problema incluso mejor que la mayoría de las proposiciones aquí.Sin embargo, en muchos lenguajes tipo C, la notación científica define un tipo de coma flotante , lo cual es desafortunado si realmente necesita un int. Sin embargo, puede escribir fácilmente esa constante para evitar conversiones implícitas en su formulario.
n / int(1e9)
se dividiría por mil millones.En su ejemplo, al tratar con cantidades físicas (tiempo en nanosegundos), generalmente me preguntaría si el entero es el tipo correcto. De hecho, un punto flotante
double
podría ser más adecuado cuando se trata de cantidades medibles (aunque, por supuesto, hay casos en los que preferiría along long
).fuente
long long
rango.Cree uno llamado NANOSECONDS_IN_ONE_SECOND en su lugar como lo que representa.
O un nombre más corto y mejor si se te ocurre uno.
fuente
Nanoseconds_Per_Second
esta es, en mi opinión, la respuesta correcta.NANOSECONDS
tiene sentido ya que no se puede saber a qué se supone que se aplica. Del mismo modo,NANOSECONDS_PER_MICROSECOND
es una constante válida similar que tiene sentido.1mm/1m = 1000
, que es exactamente el punto de lo que se está haciendo aquí.NS_PER_SEC
debería ser obvio para cualquiera que deba lidiar con nanosegundos.Las constantes están destinadas a dar significado a los números. No hay ningún significado adicional en
ONE_BILLION
a1000000000
. En realidad, lo hace más confuso, porque en diferentes idiomas naturales, ¡mil millones significa algo diferente (ya sea mil millones o un millón)! Si desea escribirlo más corto, hay una buena posibilidad de que su lenguaje de programación permita el uso de notación científica, es decir1e9
. De lo contrario, estoy de acuerdo con @JohnB, que este número realmente significa la cantidad de nanosegundos en un segundo, así que llámalo así.fuente
Para uno o dos usos, usaría la convención:
Es perfectamente explicativo, se compila a una constante y es difícil de fastidiar.
Además, es muy útil en casos como:
donde es fácil ver que estamos hablando de un día en segundos.
fuente
instance.Time = ...
, pero luego lo(1000 * 1000 * 1000)
es de tipoint
, que solo debe tener 16 bits, por lo que puede desbordarse. Puedes escribir(1000L * 1000L * 1000L)
para evitar eso.La longitud del valor no es lo que define si se necesita una constante o no.
Utiliza constantes para evitar números mágicos , no para evitar escribir.
Por ejemplo, estas son constantes perfectamente válidas:
Utilizar:
(los ejemplos de código están en Java, traduzca a su idioma favorito)
fuente
¿Un billón americano o europeo?
(o en términos técnicos, mil millones en la escala corta o larga, uno es 1000 millones, el otro es un millón).
Dada esta confusión, entonces diría que sí: tiene sentido definirlo una vez y seguir con él, del mismo modo se aplica a cualquier constante en la que necesite acordar la definición, definirla una vez.
fuente
Razones para no
En primer lugar, aquí hay una razón para no escribir guiones bajos ni utilizar ningún truco para simularlo: hace que las constantes sean más difíciles de encontrar en el código. Suponga que algún programa exhibe, en algún lugar de su operación, un valor codificado 1500000 para algún parámetro. Quiero saber en qué parte del código fuente del programa ocurre esto, así que busco el código
1500000
y no encuentro nada. ¿Por qué? Podría estar en hexadecimal (pero por qué para un número decimal tan redondo). Sin saberlo, la constante en realidad se escribe como1_500_000
. Necesitaba la expresión regular1_?500_?000
.Guiando Personajes en Comentario
El hecho de que un tipo de ayuda visual no esté disponible, o no deseamos usarlo por la razón anterior, no significa que no podamos aprovechar las dos dimensiones del archivo de texto para crear una ayuda visual alternativa:
Con esto podemos convencernos fácilmente de que hay tres grupos de tres ceros. Sin embargo, todavía podemos obtener el código fuente
1000000000
y encontrarlo.Colorear Sintaxis
Se puede hacer un editor de texto con coloración de sintaxis programable para agrupar los dígitos de los grupos en constantes numéricas con colores alternos para una mejor legibilidad. No tenemos que hacer nada en el código.
Preprocesamiento: C, C ++, Objetivo C
Ahora, si realmente queremos algunas comas entre dígitos, en C y C ++ podemos usar algún preprocesamiento:
Funciona para números como
TH(1,234,567,890)
.Una macro similar a TH también puede funcionar con pegado de token en lugar de aritmética. En el preprocesador C, el
##
operador binario ("token paste") se puede usar en un cuerpo de macro para pegar dos operandos en un solo token. Uno o ambos operandos pueden ser argumentos macro. La desventaja aquí (creando un riesgo para nosotros) es que si la catetación resultante no es un token válido, el comportamiento es indefinido.Ahora
Los programas en C que pegan los identificadores y usan los resultados para nombrar variables y funciones globales existen y son horribles para trabajar porque son impermeables a herramientas como GNU id-utils y ctags.
fuente
Sí, eso suena como una idea razonable. Los errores DIGIT off-by-one son incluso peores que los errores infames off-by-one. Sin embargo, puede crear confusión para que otras personas (incluido su yo futuro) lean el código.
Un nombre más explicativo como NANOSEC_PER_SEC parece bueno, ya que agregaría claridad donde se usa por tiempo. Sin embargo, no tiene sentido usarlo en contextos que no sean el tiempo, y no sería práctico crear 1,000,000,000 por separado para cada situación.
Lo que realmente quieres hacer, por tonto que parezca al principio, es "dividir en segundos". Esto deja a NANO_PER, que no solo es independiente del idioma (10 ^ 9 en América y Europa) sino también independiente de la situación (sin limitación en las unidades), y es fácil de escribir y leer.
fuente
En general, es una mala idea usar constantes escalares para conversiones de unidades, y si te encuentras haciendo constantes para tales cosas, estás haciendo la conversión en demasiados lugares.
Cuando tiene una cantidad de una unidad (por ejemplo, 10 segundos) y desea convertir a otra unidad (es decir, nanosegundos); este es precisamente el momento de usar el sistema de tipos de su idioma para asegurarse de que las unidades se escalen realmente como lo desea.
Hacer su función toma un
Nanoseconds
parámetro, y proporcionar a los operadores de conversión y / o constructores en este ramoSeconds
,Minutes
o lo que usted quiera. Aquí es donde suconst int
o#define
o1e9
visto en otras respuestas pertenece.Esto evita tener variables de unidades ambiguas flotando alrededor de su código; y previene franjas enteras de errores desde donde se aplicó la multiplicación / división incorrecta, o ya se aplicó, o la cantidad fue en realidad la distancia en lugar del tiempo, o ...
Además, en tales clases es bueno hacer una construcción a partir de escalares privados y usar un "MakeSeconds (int)" estático o similar para desalentar el uso descuidado de números opacos.
Más específicamente a su ejemplo, en C ++, consulte Boost.Chrono .
fuente
Personalmente, no consideraría una buena práctica crear una constante a menos que sea una constante. Si va a estar en varios lugares y tenerlo definido en la parte superior del archivo para modificación / prueba va a ser útil, entonces absolutamente.
Si es solo porque es incómodo de escribir? entonces no.
Personalmente, si obtuve el código de otra persona que tenía una constante definida, generalmente considero que este es un aspecto importante del código. Por ejemplo, tcp mantiene temporizadores vivos, número máximo de conexiones permitidas. Si tuviera que depurarlo, probablemente le prestaría mucha atención innecesaria tratando de averiguar por qué / dónde se está utilizando.
fuente
Cuando piense por qué escribió "1 mil millones" en lugar de "1000000000" en el título de su pregunta, se dará cuenta de por qué la respuesta es sí.
fuente
No cree una constante para sus grandes literales. Necesitaría una constante para cada literal, que es (en mi opinión) una broma completa. Si necesita desesperadamente aclarar sus literales sin la ayuda de elementos como el resaltado de sintaxis, podría (aunque no lo haría) crear funciones o macros para hacer su vida "más fácil":
fuente
Yo haría esto:
o
const int
SciMega = 1000 * 1000; const intSciGiga = 1000 *SciMega;Con respecto al número de nanosegundos por segundo: nano es el "inverso" de giga.
Tenga en cuenta el "Sci" - para científicos, como en las computadoras, los significados de kilo, mega, giga, etc. son diferentes: 1024 (2 ^ 10), 1024 * 1024 (2 ^ 20), etc. 2 megabytes no son 2,000,000 bytes .ACTUALIZADOR El comentarista señaló que existen términos especiales para exponentes digitales de 2: http://en.wikipedia.org/wiki/Mebibyte
fuente