Mengontrol jumlah digit desimal dalam hasil cetak di R

110

Ada opsi di R untuk mengontrol tampilan digit. Sebagai contoh:

options(digits=10)

seharusnya memberikan hasil kalkulasi dalam 10 digit hingga akhir sesi R. Di file bantuan R, definisi parameter digit adalah sebagai berikut:

digit: mengontrol jumlah digit yang akan dicetak saat mencetak nilai numerik. Ini hanya saran. Nilai yang valid adalah 1 ... 22 dengan default 7

Jadi, dikatakan ini hanya saran. Bagaimana jika saya ingin selalu menampilkan 10 digit, tidak lebih atau kurang?

Pertanyaan kedua saya adalah, bagaimana jika saya ingin menampilkan lebih dari 22 digit, yaitu untuk kalkulasi yang lebih tepat seperti 100 digit? Apakah mungkin dengan basis R, atau apakah saya memerlukan paket / fungsi tambahan untuk itu?

Edit: Terima kasih atas saran jmoy, saya mencoba sprintf("%.100f",pi)dan itu memberi

[1] "3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000"

yang memiliki 48 desimal. Apakah ini batas maksimum yang bisa ditangani R?

Mehper C. Palavuzlar
sumber
5
Hanya 15 digit pertama pi yang akurat. Bandingkan dengan nilai sebenarnya joyofpi.com/pi.html
Richie Cotton
1
Kamu benar. Mengapa berbeda di R?
Mehper C. Palavuzlar
4
Lihat FAQ di R cran.r-project.org/doc/FAQ/…
Richie Cotton
2
Mehper: Saya pikir Anda salah menafsirkan representasi komputasi angka di R. Anda mungkin ingin membaca en.wikipedia.org/wiki/Floating_point .
Shane
Sebagai perbandingan, Python melakukan hal yang persis sama: Coba python -c "import math; print(format(math.pi, '.100f'))". Hasilnya adalah pidengan 48 desimal "nyata", diisi dengan nol untuk sisa 52 digit.
kesalahan sintaks

Jawaban:

49

Alasan ini hanya saran adalah Anda dapat dengan mudah menulis fungsi cetak yang mengabaikan nilai opsi. Fungsi pencetakan dan pemformatan optionsbawaan menggunakan nilai sebagai default.

Mengenai pertanyaan kedua, karena R menggunakan aritmatika presisi hingga, jawaban Anda tidak akurat melebihi 15 atau 16 tempat desimal, jadi secara umum, lebih banyak tidak diperlukan. The GMP dan RCDD paket berurusan dengan beberapa presisi aritmatika (melalui interace ke perpustakaan GMP), tapi ini sebagian besar terkait dengan bilangan bulat besar daripada tempat desimal lebih untuk ganda Anda.

Mathematica atau Maple akan memungkinkan Anda memberikan tempat desimal sebanyak yang diinginkan hati Anda.

EDIT:
Mungkin berguna untuk memikirkan perbedaan antara tempat desimal dan angka penting. Jika Anda melakukan uji statistik yang mengandalkan perbedaan di luar angka signifikan ke-15, maka analisis Anda hampir pasti sampah.

Di sisi lain, jika Anda hanya berurusan dengan angka yang sangat kecil, itu bukan masalah, karena R dapat menangani angka sekecil .Machine$double.xmin(biasanya 2e-308).

Bandingkan kedua analisis ini.

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

Dalam kasus pertama, perbedaan antara angka hanya terjadi setelah banyak angka penting, sehingga datanya "hampir konstan". Dalam kasus kedua, Meskipun ukuran perbedaan antara bilangan sama, dibandingkan dengan besarnya bilangan itu sendiri, mereka besar.


Seperti yang disebutkan oleh e3bo, Anda dapat menggunakan bilangan floating point presisi ganda menggunakan Rmpfrpaket.

mpfr("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825")

Ini lebih lambat dan lebih banyak menggunakan memori daripada numericvektor biasa (presisi ganda) , tetapi dapat berguna jika Anda memiliki masalah yang dikondisikan dengan buruk atau algoritme yang tidak stabil.

Richie Cotton
sumber
4
Seperti yang diperlihatkan oleh halaman Rwiki ini , paket Rmpfr memungkinkan aritmatika floating point presisi tinggi di R.
e3bo
Tetapi dapatkah Rmpfr digunakan oleh paket R apa pun untuk meningkatkan presisi? Atau hanya dapat menggunakan fungsi yang dikodekan secara internal di atasnya?
skan
2
Saya hanya berpikir, "Jika Anda melakukan uji statistik yang mengandalkan perbedaan di luar angka signifikan ke-15, maka analisis Anda hampir pasti sampah." tetapi saya bertanya-tanya berapa jumlah digit yang akan saya simpulkan sebagai sampah, dan saya pikir 5, tetapi saya akan senang untuk dikoreksi.
PatrickT
46

Jika Anda memproduksi sendiri seluruh output, Anda dapat menggunakan sprintf(), mis

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

Menentukan yang ingin Anda format nomor floating point dengan poin desimal sepuluh (di %.10fdalam fadalah untuk float dan .10menspesifikasikan sepuluh poin desimal).

Saya tidak tahu cara apa pun untuk memaksa fungsi level R yang lebih tinggi untuk mencetak jumlah digit yang tepat.

Menampilkan 100 digit tidak masuk akal jika Anda mencetak angka biasa R, karena akurasi terbaik yang dapat Anda peroleh menggunakan penggandaan 64-bit adalah sekitar 16 digit desimal (lihat .Machine $ double.eps pada sistem Anda). Digit yang tersisa hanya akan menjadi sampah.

Jyotirmoy Bhattacharya
sumber
Sebenarnya, beberapa uji chi-square khusus yang saya terapkan membutuhkan ratusan desimal untuk memberikan hasil yang akurat. Pi juga memiliki ribuan desimal. Itulah mengapa saya bertanya-tanya tentang 100 digit atau lebih.
Mehper C. Palavuzlar
14
pi memiliki jumlah desimal yang tak terbatas; itu tidak berarti bahwa komputer dapat menyimpannya.
Shane
Saya kira ini adalah skenario di mana Mathematica lebih unggul dari R.
skan
1
@skan Menurut Anda, apakah Mathematica menyimpan desimal dalam jumlah tak terbatas?
Gregor Thomas
@Gregor tentu saja tidak, tetapi Anda dapat menghitung sebanyak mungkin angka yang dimungkinkan oleh memori Anda.
skan
1

Satu lagi solusi yang dapat mengontrol berapa banyak angka desimal yang akan dicetak berdasarkan kebutuhan (jika Anda tidak ingin mencetak nol yang berlebihan)

Misalnya, jika Anda memiliki vektor sebagai elementsdan ingin mendapatkan sumitu

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

Rupanya, digital terakhir yang 1telah dipotong, hasil yang ideal seharusnya -876.54321, tetapi jika ditetapkan sebagai opsi desimal pencetakan tetap, misalnya sprintf("%.10f", sum(elements)), nol yang berlebihan menghasilkan sebagai-876.5432100000

Berikut tutorialnya disini: mencetak bilangan desimal , jika mampu mengidentifikasi berapa digit desimal pada bilangan tertentu tersebut, seperti disini -876.54321ada 5 digit desimal yang perlu dicetak, maka kita dapat mengatur parameter untuk formatfungsinya seperti dibawah ini:

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

Kami dapat mengubah decimal_lengthberdasarkan setiap kueri waktu, sehingga dapat memenuhi persyaratan pencetakan desimal yang berbeda.

Lampard
sumber