que - ¿Por qué R usaría el sufijo "L" para denotar un número entero?
parseint parsefloat (1)
En R todos sabemos que es conveniente para aquellas ocasiones en las que queremos asegurarnos de que estamos tratando con un número entero para especificarlo usando el sufijo "L"
como este:
1L
# [1] 1
Si no le decimos explícitamente a R que queremos un número entero, supondrá que quisimos usar un tipo de datos numeric
...
str( 1 * 1 )
# num 1
str( 1L * 1L )
# int 1
¿Por qué es "L" el sufijo preferido, por qué no "I", por ejemplo? ¿Hay una razón histórica?
Además, ¿por qué R me permite hacer (con advertencias):
str(1.0L)
# int 1
# Warning message:
# integer literal 1.0L contains unnecessary decimal point
Pero no..
str(1.1L)
# num 1.1
#Warning message:
#integer literal 1.1L contains decimal; using numeric value
Espero que ambos devuelvan un error.
¿Por qué se usa "L" como sufijo?
Nunca lo he visto escrito, pero teorizo en resumen por dos razones:
Porque R maneja números complejos que pueden especificarse usando el sufijo
"i"
y esto sería demasiado similar a"I"
Debido a que los enteros de R son enteros largos de 32 bits y, por lo tanto, "L" parece ser una abreviatura sensible para referirse a este tipo de datos.
El valor que puede tomar un entero largo depende del tamaño de la palabra. R no admite nativamente enteros con una longitud de palabra de 64 bits. Los enteros en R tienen una longitud de palabra de 32 bits y están firmados, por lo que tienen un rango de −2,147,483,648
a 2,147,483,647
. Los valores más grandes se almacenan como double
.
Esta página wiki tiene más información sobre tipos de datos comunes, sus nombres y rangos convencionales.
Y también de ?integer
Tenga en cuenta que las implementaciones actuales de R usan enteros de 32 bits para vectores enteros, por lo que el rango de enteros representables está restringido a aproximadamente +/- 2 * 10 ^ 9: los dobles pueden contener enteros mucho más grandes exactamente.
¿Por qué 1.0L y 1.1L devuelven diferentes tipos?
La razón por la que 1.0L
y 1.1L
devolverán diferentes tipos de datos es porque devolver un entero para 1.1
dará como resultado la pérdida de información, mientras que para 1.0
no lo hará (pero es posible que desee saber que ya no tiene un punto flotante numérico). Enterrado en profundidad con el analizador léxico ( /src/main/gram.c:4463-4485
) es este código (parte de la función NumericValue()
) que en realidad crea un tipo de datos int
partir de una entrada double
que tiene el sufijo de un ascii "L"
:
/* Make certain that things are okay. */
if(c == ''L'') {
double a = R_atof(yytext);
int b = (int) a;
/* We are asked to create an integer via the L, so we check that the
double and int values are the same. If not, this is a problem and we
will not lose information and so use the numeric value.
*/
if(a != (double) b) {
if(GenerateCode) {
if(seendot == 1 && seenexp == 0)
warning(_("integer literal %s contains decimal; using numeric value"), yytext);
else {
/* hide the L for the warning message */
*(yyp-2) = ''/0'';
warning(_("non-integer value %s qualified with L; using numeric value"), yytext);
*(yyp-2) = (char)c;
}
}
asNumeric = 1;
seenexp = 1;
}
}