Controlar el número de dígitos decimales en la salida de impresión en R

110

Hay una opción en R para controlar la visualización de dígitos. Por ejemplo:

options(digits=10)

se supone que da los resultados del cálculo en 10 dígitos hasta el final de la sesión R. En el archivo de ayuda de R, la definición del parámetro de dígitos es la siguiente:

dígitos: controla el número de dígitos que se imprimirán al imprimir valores numéricos. Es solo una sugerencia. Los valores válidos son 1 ... 22 con el valor predeterminado 7

Entonces, dice que esto es solo una sugerencia. ¿Qué pasa si me gusta mostrar siempre 10 dígitos, ni más ni menos?

Mi segunda pregunta es, ¿qué pasa si me gusta mostrar más de 22 dígitos, es decir, para cálculos más precisos como 100 dígitos? ¿Es posible con la base R, o necesito un paquete / función adicional para eso?

Editar: Gracias a la sugerencia de jmoy, lo intenté sprintf("%.100f",pi)y me dio

[1] "3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000"

que tiene 48 decimales. ¿Es este el límite máximo que R puede manejar?

Mehper C. Palavuzlar
fuente
5
Solo los primeros 15 dígitos de pi son precisos. Comparar con el valor real joyofpi.com/pi.html
Richie Cotton
1
Tienes razón. ¿Por qué es diferente en R?
Mehper C. Palavuzlar
4
Consulte las preguntas frecuentes en R cran.r-project.org/doc/FAQ/…
Richie Cotton
2
Mehper: Creo que estás malinterpretando la representación computacional de números en R. Es posible que desees leer en.wikipedia.org/wiki/Floating_point .
Shane
Como comparación, Python hace exactamente lo mismo: probar python -c "import math; print(format(math.pi, '.100f'))". El resultado es picon 48 decimales "reales", rellenos de ceros para los 52 dígitos restantes.
error de sintaxis

Respuestas:

49

La razón por la que es solo una sugerencia es que podría escribir fácilmente una función de impresión que ignorara el valor de las opciones. Las funciones de impresión y formato integradas utilizan el optionsvalor como predeterminado.

En cuanto a la segunda pregunta, dado que R usa aritmética de precisión finita, sus respuestas no son precisas más allá de 15 o 16 lugares decimales, por lo que, en general, no se requieren más. Los paquetes gmp y rcdd tratan con aritmética de precisión múltiple (a través de una interfaz a la biblioteca gmp), pero esto se relaciona principalmente con números enteros grandes en lugar de más lugares decimales para sus dobles.

Mathematica o Maple te permitirán dar tantos lugares decimales como tu corazón desee.

EDITAR:
Podría ser útil pensar en la diferencia entre lugares decimales y cifras significativas. Si está haciendo pruebas estadísticas que se basan en diferencias más allá de la decimoquinta cifra significativa, es casi seguro que su análisis es basura.

Por otro lado, si solo está tratando con números muy pequeños, eso es un problema menor, ya que R puede manejar números tan pequeños como .Machine$double.xmin(generalmente 2e-308).

Compare estos dos análisis.

x1 <- rnorm(50, 1, 1e-15)
y1 <- rnorm(50, 1 + 1e-15, 1e-15)
t.test(x1, y1)  #Should throw an error

x2 <- rnorm(50, 0, 1e-15)
y2 <- rnorm(50, 1e-15, 1e-15)
t.test(x2, y2)  #ok

En el primer caso, las diferencias entre números solo ocurren después de muchas cifras significativas, por lo que los datos son "casi constantes". En el segundo caso, aunque el tamaño de las diferencias entre números es el mismo, en comparación con la magnitud de los números en sí, son grandes.


Como lo menciona e3bo, puede usar números de punto flotante de precisión múltiple usando el Rmpfrpaquete.

mpfr("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825")

Son más lentos y de uso más intensivo en memoria que los numericvectores regulares (precisión doble) , pero pueden ser útiles si tiene un problema mal acondicionado o un algoritmo inestable.

Richie algodón
fuente
4
Como demuestra esta página de Rwiki , el paquete Rmpfr permite aritmética de punto flotante de alta precisión en R.
e3bo
Pero, ¿cualquier paquete R puede utilizar Rmpfr para mejorar su precisión? ¿O solo puede usar las funciones codificadas internamente en él?
skan
2
Estaba pensando en eso, "si está haciendo pruebas estadísticas que se basan en diferencias más allá de la decimoquinta cifra significativa, entonces su análisis es casi seguro que es basura". pero me preguntaba cuál sería la cantidad de dígitos en los que concluiría que es basura, y pensé 5, pero estaría feliz de quedar corregido.
PatrickT
46

Si está produciendo la salida completa usted mismo, puede usar sprintf(), por ejemplo

> sprintf("%.10f",0.25)
[1] "0.2500000000"

especifica que desea formatear un número de punto flotante con diez puntos decimales (en %.10fel fes para flotante y .10especifica diez puntos decimales).

No conozco ninguna forma de obligar a las funciones de nivel superior de R a imprimir un número exacto de dígitos.

Mostrar 100 dígitos no tiene sentido si está imprimiendo los números habituales de R, ya que la mejor precisión que puede obtener usando dobles de 64 bits es alrededor de 16 dígitos decimales (mire .Machine $ double.eps en su sistema). Los dígitos restantes serán simplemente basura.

Jyotirmoy Bhattacharya
fuente
En realidad, algunas pruebas especiales de chi-cuadrado que apliqué necesitaban cientos de decimales para dar resultados precisos. También pi tiene miles de decimales. Por eso me preguntaba unos 100 o más dígitos.
Mehper C. Palavuzlar
14
pi tiene un número infinito de decimales; eso no significa que una computadora pueda almacenarlos.
Shane
Supongo que este es un escenario en el que Mathematica es superior a R.
skan
1
@skan ¿Crees que Mathematica almacena una cantidad infinita de decimales?
Gregor Thomas
@ Gregor, por supuesto que no, pero puedes usar tantos dígitos como te permita tu memoria.
skan
1

Una solución más capaz de controlar cuántos dígitos decimales imprimir según las necesidades (si no desea imprimir ceros redundantes)

Por ejemplo, si usted tiene un vector como elementsy le gustaría obtener sumde ella

elements <- c(-1e-05, -2e-04, -3e-03, -4e-02, -5e-01, -6e+00, -7e+01, -8e+02)
sum(elements)
## -876.5432

Aparentemente, el último digital como 1truncado, el resultado ideal debería ser -876.54321, pero si se establece como una opción decimal de impresión fija, por ejemplo sprintf("%.10f", sum(elements)), cero redundante generar como-876.5432100000

Siguiendo el tutorial aquí: imprimiendo números decimales , si es capaz de identificar cuántos dígitos decimales en un determinado número numérico, como aquí en -876.54321, hay 5 dígitos decimales que se deben imprimir, entonces podemos configurar un parámetro para la formatfunción como se muestra a continuación:

decimal_length <- 5
formatC(sum(elements), format = "f", digits = decimal_length)
## -876.54321

Podemos cambiar el decimal_lengthbasado en cada consulta de tiempo, por lo que puede satisfacer diferentes requisitos de impresión decimal.

Lampard
fuente