Kontrolowanie liczby cyfr dziesiętnych w wydruku w R

110

W R jest opcja uzyskania kontroli nad wyświetlaniem cyfr. Na przykład:

options(digits=10)

ma podawać wyniki obliczeń w 10 cyfrach do końca sesji R. W pliku pomocy R, definicja parametru cyfry jest następująca:

cyfry: kontroluje liczbę cyfr do wydrukowania podczas drukowania wartości liczbowych. To tylko sugestia. Prawidłowe wartości to 1 ... 22, domyślnie 7

Więc mówi, że to tylko sugestia. Co jeśli lubię zawsze wyświetlać 10 cyfr, a nie mniej lub więcej?

Moje drugie pytanie brzmi: co zrobić, jeśli lubię wyświetlać więcej niż 22 cyfry, czyli do bardziej precyzyjnych obliczeń, takich jak 100 cyfr? Czy jest to możliwe z podstawowym R, czy potrzebuję do tego dodatkowego pakietu / funkcji?

Edycja: Dzięki sugestii jmoy spróbowałem sprintf("%.100f",pi)i dałem

[1] "3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000"

który ma 48 miejsc po przecinku. Czy to jest maksymalny limit, z którym R może sobie poradzić?

Mehper C. Palavuzlar
źródło
5
Tylko pierwsze 15 cyfr pi jest dokładnych. Porównaj z prawdziwą wartością joyofpi.com/pi.html
Richie Cotton
1
Masz rację. Dlaczego jest inaczej w R?
Mehper C. Palavuzlar
4
Zobacz FAQ na R cran.r-project.org/doc/FAQ/ ...
Richie Cotton
2
Mehper: Myślę, że błędnie interpretujesz obliczeniową reprezentację liczb w R. Możesz przeczytać en.wikipedia.org/wiki/Floating_point .
Shane,
Dla porównania Python robi dokładnie to samo: spróbuj python -c "import math; print(format(math.pi, '.100f'))". Wynikiem jest pi48 „prawdziwych” miejsc po przecinku, wypełnionych zerami dla pozostałych 52 cyfr.
błąd składni

Odpowiedzi:

49

Powodem, dla którego jest to tylko sugestia, jest to, że można dość łatwo napisać funkcję drukującą, która ignorowała wartość opcji. Wbudowane funkcje drukowania i formatowania używają tej optionswartości jako domyślnej.

Jeśli chodzi o drugie pytanie, ponieważ R używa arytmetyki o skończonej precyzji, twoje odpowiedzi nie są dokładne poza 15 lub 16 miejscami po przecinku, więc generalnie więcej nie jest wymagane. W GMP i rcdd pakiety czynienia z wieloma precyzji arytmetyki (poprzez interace do biblioteki GMP), ale jest to związane głównie z dużych liczb całkowitych zamiast większej ilości miejsc po przecinku dla swoich sobowtórów.

Mathematica lub Maple pozwolą ci podać tyle miejsc po przecinku, ile dusza zapragnie.

EDYCJA:
Warto pomyśleć o różnicy między miejscami dziesiętnymi a cyframi znaczącymi. Jeśli wykonujesz testy statystyczne, które opierają się na różnicach wykraczających poza piętnastą cyfrę znaczącą, to Twoja analiza jest prawie na pewno śmieciowa.

Z drugiej strony, jeśli masz do czynienia tylko z bardzo małymi liczbami, jest to mniejszy problem, ponieważ R może obsłużyć liczbę tak małą, jak .Machine$double.xmin(zwykle 2e-308).

Porównaj te dwie analizy.

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

W pierwszym przypadku różnice między liczbami pojawiają się dopiero po wielu cyfrach znaczących, więc dane są „prawie stałe”. W drugim przypadku, chociaż wielkość różnic między liczbami jest taka sama, w porównaniu z wielkością samych liczb są one duże.


Jak wspomniano w e3bo, możesz używać liczb zmiennoprzecinkowych o dużej precyzji używając Rmpfrpakietu.

mpfr("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825")

Są wolniejsze i wymagają więcej pamięci niż zwykłe numericwektory (o podwójnej precyzji) , ale mogą być przydatne, jeśli masz źle uwarunkowany problem lub niestabilny algorytm.

Richie Cotton
źródło
4
Jak to strona Rwiki demonstruje The pakiet Rmpfr pozwala na wysokiej precyzji arytmetyki zmiennoprzecinkowej w R.
e3bo
Ale czy Rmpfr może być używane przez dowolny pakiet R, aby poprawić jego precyzję? Czy może używać tylko funkcji zakodowanych na nim wewnętrznie?
skan
2
Pomyślałem tylko o tym: „Jeśli robisz testy statystyczne, które opierają się na różnicach wykraczających poza 15. cyfrę znaczącą, to Twoja analiza jest prawie na pewno śmieciowa”. ale zastanawiałem się, jaka byłaby liczba cyfr, przy których uznałbym, że to śmieci, i pomyślałem, że 5, ale byłbym szczęśliwy, gdybym został poprawiony.
PatrickT
46

Jeśli sam produkujesz całość, możesz użyć sprintf()np

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

Określa, że należy sformatować liczbę zmiennoprzecinkową z dziesięciu miejsc po przecinku (w jest dla pływaka oraz wyszczególnia dziesięć miejsc po przecinku).%.10ff.10

Nie znam żadnego sposobu na zmuszenie funkcji wyższego poziomu R do wypisywania dokładnej liczby cyfr.

Wyświetlanie 100 cyfr nie ma sensu, jeśli drukujesz zwykłe liczby R, ponieważ najlepsza dokładność, jaką można uzyskać za pomocą 64-bitowych podwójnych liczb, to około 16 cyfr dziesiętnych (spójrz na .Machine $ double.eps w twoim systemie). Pozostałe cyfry będą po prostu śmieciami.

Jyotirmoy Bhattacharya
źródło
W rzeczywistości niektóre specjalne testy chi-kwadrat, które zastosowałem, wymagały setek miejsc po przecinku, aby dać dokładne wyniki. Pi ma również tysiące miejsc po przecinku. Dlatego zastanawiałem się około 100 lub więcej cyfr.
Mehper C. Palavuzlar
14
pi ma nieskończoną liczbę miejsc po przecinku; nie oznacza to, że komputer może je przechowywać.
Shane,
Myślę, że to scenariusz, w którym Mathematica jest lepsza od R.
skan
1
@skan Czy uważasz, że Mathematica przechowuje nieskończoną liczbę miejsc po przecinku?
Gregor Thomas
@Gregor oczywiście, że nie, ale możesz podać tyle cyfr, na ile pozwala ci pamięć.
skan
1

Jeszcze jedno rozwiązanie pozwalające kontrolować, ile cyfr dziesiętnych ma zostać wydrukowanych w zależności od potrzeb (jeśli nie chcesz drukować zbędnych zer)

Na przykład, jeśli masz wektora jak elementsi chciałby uzyskać sumod niego

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

Najwyraźniej ostatnia cyfra 1została obcięta, idealny wynik powinien być -876.54321, ale jeśli jest ustawiony jako stała opcja drukowania dziesiętnego, np. sprintf("%.10f", sum(elements))Nadmiarowe zero (s) generuje jako-876.5432100000

Postępując zgodnie z samouczkiem tutaj: drukowanie liczb dziesiętnych , jeśli -876.54321jesteśmy w stanie określić, ile cyfr dziesiętnych w określonej liczbie liczbowej, tak jak tutaj , jest 5 cyfr dziesiętnych do wydrukowania, możemy ustawić parametr dla formatfunkcji, jak poniżej:

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

Możemy zmienić na decimal_lengthpodstawie każdego zapytania czasowego, aby spełniał różne wymagania dotyczące drukowania dziesiętnego.

Lampard
źródło