Bagaimana saya bisa melakukan math.ceil
sehingga suatu nomor ditugaskan ke kekuatan tertinggi berikutnya 10?
# 0.04 -> 0.1
# 0.7 -> 1
# 1.1 -> 10
# 90 -> 100
# ...
Solusi saya saat ini adalah kamus yang memeriksa kisaran nomor input, tetapi hardcoded dan saya lebih suka solusi satu-liner. Mungkin saya kehilangan trik matematika sederhana atau fungsi numpy yang sesuai di sini?
10
atas, ini akan membutuhkan sesuatu dengan misalnyalog10
.Jawaban:
Anda dapat menggunakan
math.ceil
denganmath.log10
melakukan hal ini:log10(n)
memberi Anda solusix
yang memuaskan10 ** x == n
, jadi jika Anda mengumpulkannyax
memberi Anda eksponen untuk kekuatan tertinggi berikutnya 10.Catatan bahwa untuk nilai
n
di manax
sudah merupakan integer, "kekuasaan tertinggi berikutnya 10" akann
:sumber
10 ** math.ceil(math.log10(1)) == 1
, yang bukan "kekuatan tertinggi berikutnya"Masalah Anda tidak ditentukan, Anda harus mundur dan mengajukan beberapa pertanyaan.
Di jawaban lain diusulkan untuk mengambil logaritma, kemudian mengumpulkan (fungsi langit-langit), kemudian eksponensial.
Sayangnya ini mengalami kesalahan pembulatan. Pertama-tama n dikonversi dari tipe data apa pun yang kebetulan terjadi menjadi angka floating point presisi ganda, yang berpotensi menimbulkan kesalahan pembulatan, kemudian logaritma dihitung berpotensi menimbulkan lebih banyak kesalahan pembulatan baik dalam perhitungan internal maupun dalam hasilnya.
Karena itu tidak butuh waktu lama bagi saya untuk menemukan contoh yang memberikan hasil yang salah.
Secara teori juga mungkin untuk gagal ke arah lain, meskipun ini tampaknya jauh lebih sulit untuk diprovokasi.
Jadi untuk solusi yang kuat untuk float dan int kita perlu mengasumsikan bahwa nilai logaritma kita hanya perkiraan, dan karena itu kita harus menguji beberapa kemungkinan. Sesuatu di sepanjang garis
Saya percaya kode ini harus memberikan hasil yang benar untuk semua argumen dalam jangkauan dunia nyata yang masuk akal. Ini akan pecah untuk jumlah yang sangat kecil atau sangat besar dari tipe non integer dan non-floating point karena masalah mengubahnya menjadi floating point. Argumen integer kasus khusus Python untuk fungsi log10 dalam upaya untuk mencegah overflow, tetapi masih dengan integer yang cukup besar mungkin dapat memaksa hasil yang salah karena kesalahan pembulatan.
Untuk menguji dua implementasi saya menggunakan program tes berikut.
Ini menemukan banyak kegagalan dalam implementasi yang naif, tetapi tidak ada dalam implementasi yang ditingkatkan.
sumber
round
bukanmath.ceil
? Ini akan memperkenalkan banyak kasus yang tidak perlu di tempatr < n
yang benar sehingga perlu melakukan pekerjaan tambahan.Tampaknya Anda menginginkan kekuatan 10 terendah berikutnya ... Berikut adalah cara menggunakan matematika murni dan tidak ada log, tetapi rekursi.
sumber
Mungkin sesuatu seperti ini? Itu hanya dari atas kepala saya tetapi berhasil ketika saya mencoba beberapa angka di terminal.
sumber
Lihat ini!
Kode ini berdasarkan prinsip kekuatan sepuluh di
len( str( int( float_number ) ) )
.Ada 4 kasus:
int( i ) > 1
.Float
Nomor - dikonversi keint
, setelah talistr()
dari itu, akan memberi kitastring
denganlength
yang kita cari persis. Jadi, bagian pertama, untuk inputi > 1.0
- itu adalah sepuluh10
kekuatan sepanjang ini.i > 1.0
dani > 0.1
<=> itu10
dan1
masing - masing.i < 0.1
: Di sini, sepuluh akan berada dalam kekuatan negatif. Untuk mendapatkan elemen bukan nol pertama setelah koma, saya telah menggunakan konstruksi seperti itu("%.100f" % i ).replace('.','').index( k )
, di mana k dijalankan dengan[1:10]
interval. Setelah itu, ambil minimal daftar hasil. Dan berkurang satu, itu nol pertama, yang akan dihitung. Juga, di sini standar python iniindex()
mungkin macet, jika tidak akan menemukan setidaknya satu dari non zero-elemen dari[1:10]
selang, itu sebabnya pada akhirnya saya harus "filter" daftar oleh terjadinya:if str( j ) in "%.100f" % i
. Selain itu, untuk mendapatkan ketelitian yang lebih dalam -%.100f
dapat dianggap berbeda.sumber