Saya mencoba memperkirakan kompleksitas suatu algoritma yang saya tulis untuk dekompiler Reko , di mana saya mencoba untuk "membatalkan" tranformasi yang dilakukan oleh kompiler ke divisi integer oleh konstanta. Kompiler telah mengubah divisi menjadi perkalian integer dan pergeseran:dimana adalah jumlah bit kata mesin komputer. Perkalian konstan yang dihasilkan jauh lebih cepat daripada pembagian di sebagian besar arsitektur kontemporer, tetapi tidak lagi menyerupai kode asli.
Untuk menggambarkan: pernyataan C.
y = x / 10;
akan dikompilasi oleh kompiler Microsoft Visual C ++ ke bahasa assembly berikut
mov edx,1999999Ah ; load 1/10 * 2^32
imul eax ; edx:eax = dividend / 10 * 2 ^32
mov eax,edx ; eax = dividend / 10
Hasil akhirnya adalah register eax
sekarang akan memiliki nilai yang diharapkan dari y
kode sumber.
Decompiler naif akan mendekompilasi di atas ke
eax = ((long)eax * 0x1999999A) >> 32;
tetapi Reko bertujuan untuk membuat output yang dihasilkan lebih terbaca dari itu dengan memulihkan konstanta yang digunakan di divisi asli.
Algoritma yang diisyaratkan di atas didasarkan pada deskripsi pada artikel ini di Wikipedia . Pertama, algoritma memperlakukan pengali konstan sebagai timbal balik yang diskalakan. Itu mengubahnya menjadi angka floating point dan kemudian skala turun untuk dimana . Langkah terakhir yang mahal adalah mengurung nilai floating point antara dua bilangan rasional , (dimulai dengan 0/1 dan 1/1) dan berulang kali menghitung perantara sampai beberapa kriteria konvergensi tercapai. Hasilnya harus menjadi pendekatan rasional "terbaik" untuk timbal balik .
Sekarang, jika bracketing sedang dilakukan dengan pencarian biner yang khas dimulai antara rasional dan , dan menghitung titik tengah , Saya berharap algoritma akan menyatu Langkah. Tapi apa kompleksitas algoritma jika mediant digunakan sebagai gantinya?
sumber
Jawaban:
Hubungan antara pohon Stern-Brocot dan urutan Farey menunjukkan bahwa jika0 < p / q< 1 dan ( p , q) = 1 (yaitu, p / q adalah fraksi yang berkurang) p / q ada di q tingkat pohon. Karena jangka waktu menjalankan algoritma Anda linear pada tingkat di mana Anda mengakhiri, algoritma Anda membutuhkan waktuO ( q) dimana p / q adalah jawabannya; tapi ini tidak begitu membantu.
Anda belum menentukan kriteria berhenti Anda, tetapi mungkin Anda memiliki beberapa ambang kesalahanϵ . Oleh karena itu pertanyaannya adalah untuk urutan Farey apakah kasus istilah yang paling jauh jaraknya2 ϵ (dan setiap titik berada jauh ϵ dari beberapa titik). Menggunakan fakta bahwa jarak antara fraksi yang berdekatanhal1/q1,hal2/q2 dalam urutan Farey adalah 1 / (q1q2) , tidak sulit untuk menunjukkan bahwa jarak maksimal pada q Urutan Farey adalah 1 / q . Karena itu jika Anda membidik jarakϵ , maka algoritma Anda akan berjalan dalam waktu O ( 1 / ϵ ) dalam kasus terburuk.
Namun, "sebagian besar" fraksi yang berdekatan diq Urutan Farey berada di kejauhan O ( 1 /q2) , dan rata-rata Anda mungkin mengharapkan waktu berjalan O (1 / ϵ---√) (sayangnya, rata-rata ini berkaitan dengan input daripada algoritma).
sumber