Controlando o número de dígitos decimais na saída de impressão em R

110

Existe uma opção em R para obter controle sobre a exibição de dígitos. Por exemplo:

options(digits=10)

deve fornecer os resultados do cálculo em 10 dígitos até o final da sessão R. No arquivo de ajuda de R, a definição do parâmetro de dígitos é a seguinte:

dígitos: controla o número de dígitos a serem impressos ao imprimir valores numéricos. É apenas uma sugestão. Os valores válidos são 1 ... 22 com padrão 7

Portanto, diz que é apenas uma sugestão. E se eu gostar de sempre exibir 10 dígitos, nem mais nem menos?

Minha segunda pergunta é: e se eu gostar de exibir mais de 22 dígitos, ou seja, para cálculos mais precisos como 100 dígitos? É possível com a base R ou preciso de um pacote / função adicional para isso?

Edit: Graças à sugestão de jmoy, eu tentei sprintf("%.100f",pi)e deu

[1] "3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000"

que tem 48 casas decimais. Este é o limite máximo que R pode suportar?

Mehper C. Palavuzlar
fonte
5
Apenas os primeiros 15 dígitos de pi são precisos. Compare com o valor verdadeiro joyofpi.com/pi.html
Richie Cotton
1
Você está certo. Por que é diferente em R?
Mehper C. Palavuzlar
4
Veja o FAQ em R cran.r-project.org/doc/FAQ/…
Richie Cotton
2
Mehper: Acho que você está interpretando mal a representação computacional de números em R. Você pode querer ler en.wikipedia.org/wiki/Floating_point .
Shane
Como comparação, Python faz exatamente o mesmo: Experimente python -c "import math; print(format(math.pi, '.100f'))". O resultado são pi48 decimais "reais", preenchidos por zeros para os 52 dígitos restantes.
erro de sintaxe

Respostas:

49

A razão de ser apenas uma sugestão é que você poderia facilmente escrever uma função de impressão que ignorasse o valor das opções. As funções integradas de impressão e formatação usam o optionsvalor como padrão.

Quanto à segunda pergunta, como R usa aritmética de precisão finita, suas respostas não são precisas além de 15 ou 16 casas decimais, portanto, em geral, não são necessárias mais. Os pacotes gmp e rcdd lidam com aritmética de precisão múltipla (por meio de uma interação com a biblioteca gmp), mas isso está relacionado principalmente a números inteiros grandes em vez de mais casas decimais para seus duplos.

O Mathematica ou o Maple permitirão que você dê quantas casas decimais você desejar.

EDIT:
Pode ser útil pensar sobre a diferença entre casas decimais e algarismos significativos. Se você estiver fazendo testes estatísticos que dependem de diferenças além do 15º algarismo significativo, então sua análise é quase certamente um lixo.

Por outro lado, se você está lidando apenas com números muito pequenos, isso não é um problema, pois R pode lidar com números tão pequenos quanto .Machine$double.xmin(geralmente 2e-308).

Compare essas duas análises.

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

No primeiro caso, as diferenças entre os números só ocorrem depois de muitos algarismos significativos, portanto, os dados são "quase constantes". No segundo caso, embora o tamanho das diferenças entre os números seja o mesmo, em comparação com a magnitude dos próprios números, eles são grandes.


Conforme mencionado pelo e3bo, você pode usar números de ponto flutuante de precisão múltipla usando o Rmpfrpacote.

mpfr("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825")

Eles são mais lentos e usam mais memória do que os numericvetores regulares (precisão dupla) , mas podem ser úteis se você tiver um problema mal condicionado ou algoritmo instável.

Algodão rico
fonte
4
Como esta página Rwiki demonstra, o pacote Rmpfr permite aritmética de ponto flutuante de alta precisão em R.
e3bo
Mas o Rmpfr pode ser usado por qualquer pacote R para melhorar sua precisão? Ou ele só pode usar as funções codificadas internamente nele?
skan
2
Eu estava pensando apenas que, "Se você está fazendo testes estatísticos que dependem de diferenças além do décimo quinto algarismo significativo, então sua análise quase certamente é lixo." mas me perguntei qual seria o número de dígitos em que eu concluiria que é lixo e pensei 5, mas ficaria feliz em ser corrigido.
PatrickT
46

Se você está produzindo toda a produção sozinho, pode usar sprintf(), por exemplo

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

Especifica que você deseja formatar um número de ponto flutuante com pontos decimais dez (em %.10fo fé para bóia e as .10especifica pontos decimais dez).

Não conheço nenhuma maneira de forçar as funções de nível superior de R a imprimir um número exato de dígitos.

Exibir 100 dígitos não faz sentido se você estiver imprimindo os números usuais de R, já que a melhor precisão que você pode obter usando duplos de 64 bits é em torno de 16 dígitos decimais (veja .Machine $ double.eps em seu sistema). Os dígitos restantes serão apenas lixo.

Jyotirmoy Bhattacharya
fonte
Na verdade, alguns testes especiais de qui-quadrado que apliquei precisavam de centenas de decimais para fornecer resultados precisos. Além disso, pi tem milhares de decimais. É por isso que eu queria saber cerca de 100 ou mais dígitos.
Mehper C. Palavuzlar
14
pi tem um número infinito de decimais; isso não significa que um computador possa armazená-los.
Shane
Eu acho que este é um cenário onde o Mathematica é superior ao R.
skan
1
@skan Você acha que o Mathematica armazena um número infinito de decimais?
Gregor Thomas
@Gregor é claro que não, mas você pode usar tantos dígitos quanto sua memória permitir.
skan
1

Mais uma solução capaz de controlar quantos dígitos decimais imprimir com base nas necessidades (se você não quiser imprimir zero (s) redundante (s))

Por exemplo, se você tem um vetor como elementse gostaria de obtê- sumlo

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

Aparentemente, o último digital 1foi truncado, o resultado ideal deve ser -876.54321, mas se definido como opção decimal de impressão fixa, por exemplo sprintf("%.10f", sum(elements)), zero (s) redundante (s) gera como-876.5432100000

Seguindo o tutorial aqui: imprimindo números decimais , se conseguirmos identificar quantos dígitos decimais em um determinado número numérico, como aqui em -876.54321, há 5 dígitos decimais que precisam ser impressos, então podemos configurar um parâmetro para formatfunção conforme abaixo:

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

Podemos alterar a decimal_lengthconsulta com base em cada vez, para que possa atender a diferentes requisitos de impressão decimal.

Lampard
fonte