Saya diminta untuk menghitung ekspresi root bersarang berikut ini hanya menggunakan rekursi .
Saya menulis kode di bawah ini yang berfungsi, tetapi mereka memungkinkan kami untuk menggunakan hanya satu fungsi dan 1 input n
untuk tujuan dan bukan 2 seperti yang saya gunakan. Dapatkah seseorang membantu saya mengubah kode ini menjadi satu fungsi yang akan menghitung ekspresi? tidak dapat menggunakan perpustakaan apa pun kecuali fungsi dari <math.h>
.
output untuk n = 10: 1.757932
double rec_sqrt_series(int n, int m) {
if (n <= 0)
return 0;
if (m > n)
return 0;
return sqrt(m + rec_sqrt_series(n, m + 1));
}
double helper(int n) {
return rec_sqrt_series(n, 1);
}
helper
?abort()
(dari<stdlib.h>
), tidak diam-diam mengembalikan 0.double nested_root(unsigned n) { double x = 0.0; if (n > 0) { x = nested_root(0); for (unsigned i = n; i > 0; i--) { x = sqrt(i + x); } } return x; }
Jawaban:
Gunakan bit atas
n
sebagai penghitung:Tentu, bahwa malfungsi ketika awal
n
adalahR
atau lebih besar. Berikut adalah versi yang lebih rumit yang berfungsi untuk nilai positif apa pun darin
. Berhasil:n
negatif, ini berfungsi seperti versi di atas, menggunakan bit atas untuk menghitung.n
positif, jika kurang dariR
itu, ia memanggil dirinya sendiri-n
untuk mengevaluasi fungsi seperti di atas. Kalau tidak, itu menyebut dirinya denganR-1
negasi. Ini mengevaluasi fungsi seolah-olah dipanggil denganR-1
. Ini menghasilkan hasil yang benar karena seri berhenti berubah dalam format floating-point setelah hanya beberapa lusin iterasi - akar kuadrat dari angka yang lebih dalam menjadi sangat terdilusi sehingga tidak memiliki efek. Jadi fungsinya memiliki nilai yang sama untuk seluruhn
ambang batas yang kecil.sumber
R
terpisah, jadi bisa disetel. Sebelumn
mencapai 32, nilai kembali berhenti berubah untuk IEEE-754 binary64, dan sebelum mencapai 256, nilai kembali berhenti berubah untuk format yang masuk akal untukdouble
. Jadi saya sedang mempertimbangkan versi alternatif yang mengubah input klem di atasR
, tetapi perlu menggunakan bit tanda, dan saya masih mengerjakannya.n
terlepas dari lebarint
.Tanpa mengubah rumus secara matematis (saya tidak tahu apakah itu mungkin), Anda tidak dapat benar-benar menggunakan hanya satu parameter, karena untuk setiap elemen Anda memerlukan dua informasi: langkah saat ini dan yang asli
n
. Namun Anda bisa menipu . Salah satu caranya adalah menyandikan dua angka dalamint
parameter (seperti yang ditunjukkan oleh Eric ).Cara lain adalah dengan menyimpan yang asli
n
dalam variabel lokal statis. Pada panggilan pertama kita simpann
dalam variabel statis ini, kita memulai rekursi dan pada langkah terakhir kita meresetnya ke nilai sentinel:Rupanya
static int n = sentinel
bukan standar C karenasentinel
bukan waktu kompilasi konstan dalam C (itu aneh karena baik gcc dan dentang tidak mengeluh, bahkan dengan-pedantic
)Anda bisa melakukan ini sebagai gantinya:
sumber
static int n = sentinel;
tidak sepenuhnya sesuai dalam C karenasentinel
tidak ekspresi konstan sesuai Standar C. Ia bekerja di C ++, dan dikompilasi dengan versi gcc dan clang saat ini dalam mode C tetapi tidak pada MSVC 2017, tetapi Anda mungkin harus menulisstatic int n = -1;
lihat godbolt.org/z/8pEMnzMasalah ini memohon solusi berkerut.
Berikut ini adalah yang menggunakan fungsi tunggal yang mengambil satu atau dua
int
argumen:<stdarg.h>
yang mungkin atau mungkin tidak diizinkan.Ini kodenya:
Berikut adalah solusi lain dengan fungsi tunggal, hanya menggunakan
<math.h>
, tetapi menyalahgunakan aturan dengan cara yang berbeda: menggunakan makro.Namun satu lagi, secara tegas rekursif , tetapi dengan tingkat rekursi tunggal dan tidak ada trik lain. Seperti yang dikomentari Eric , itu menggunakan
for
loop yang mungkin tidak valid di bawah batasan OP:sumber
double rec_sqrt_series(int n)
, IMO, memenuhi tujuan OP dengan menggunakan tanda sebagai bendera rekursi. (Saya akan menjatuhkan yangelse
tidak diperlukan seperti yangreturn
ada diif
.)else
mungkin mungkin tapi saya agak suka simetri dari kedua cabang dariif
mengembalikan hasil, semacam gaya pemrograman fungsional.Ini pendekatan lain.
Itu bergantung pada
int
32 bit. Idenya adalah untuk menggunakan bit 32 atas 64 bitint
untuk1) Lihat apakah panggilan itu panggilan rekursif (atau panggilan dari "luar")
2) Simpan nilai target dalam 32 bit atas selama rekursi
sumber