Saya ingin menghapus digit dari float agar memiliki jumlah digit tetap setelah titik, seperti:
1.923328437452 -> 1.923
Saya perlu mengeluarkan sebagai string ke fungsi lain, bukan mencetak.
Juga saya ingin mengabaikan digit yang hilang, bukan membulatkannya.
python
floating-point
Joan Venge
sumber
sumber
Jawaban:
Pertama, fungsinya, bagi mereka yang hanya menginginkan kode salin dan tempel:
Ini berlaku di Python 2.7 dan 3.1+. Untuk versi yang lebih lama, tidak mungkin untuk mendapatkan efek "pembulatan cerdas" yang sama (setidaknya, bukan tanpa banyak kode yang rumit), tetapi pembulatan ke 12 tempat desimal sebelum pemotongan akan sering dilakukan:
Penjelasan
Inti dari metode yang mendasari adalah mengubah nilai menjadi string dengan presisi penuh dan kemudian memotong semuanya di luar jumlah karakter yang diinginkan. Langkah terakhir ini mudah; itu bisa dilakukan baik dengan manipulasi string
atau
decimal
modulLangkah pertama, mengubah ke string, cukup sulit karena ada beberapa pasangan literal floating point (yaitu apa yang Anda tulis di kode sumber) yang keduanya menghasilkan representasi biner yang sama namun harus dipotong secara berbeda. Misalnya, pertimbangkan 0,3 dan 0,29999999999999998. Jika Anda menulis
0.3
dalam program Python, kompilator mengkodekannya menggunakan format titik-mengambang IEEE ke dalam urutan bit (dengan asumsi float 64-bit)Ini adalah nilai terdekat dengan 0,3 yang secara akurat dapat direpresentasikan sebagai float IEEE. Tetapi jika Anda menulis
0.29999999999999998
dalam program Python, kompilator menerjemahkannya menjadi nilai yang persis sama . Dalam satu kasus, Anda bermaksud memangkasnya (menjadi satu digit) sebagai0.3
, sedangkan dalam kasus lain Anda bermaksud memangkasnya0.2
, tetapi Python hanya dapat memberikan satu jawaban. Ini adalah batasan mendasar Python, atau memang bahasa pemrograman apa pun tanpa evaluasi malas. Fungsi pemotongan hanya memiliki akses ke nilai biner yang disimpan di memori komputer, bukan string yang sebenarnya Anda ketikkan ke dalam kode sumber. 1Jika Anda mendekode urutan bit kembali menjadi angka desimal, sekali lagi menggunakan format titik mengambang IEEE 64-bit, Anda mendapatkan
jadi implementasi yang naif akan muncul
0.2
meskipun itu mungkin bukan yang Anda inginkan. Untuk lebih lanjut tentang kesalahan representasi floating-point, lihat tutorial Python .Sangat jarang bekerja dengan nilai floating-point yang sangat dekat dengan bilangan bulat tetapi sengaja tidak sama dengan bilangan bulat itu. Jadi, saat memotong, mungkin masuk akal untuk memilih representasi desimal "terbaik" dari semua yang dapat sesuai dengan nilai dalam memori. Python 2.7 dan yang lebih baru (tetapi bukan 3.0) menyertakan algoritme canggih untuk melakukan hal itu , yang dapat kita akses melalui operasi pemformatan string default.
Satu-satunya peringatan adalah bahwa ini bertindak seperti
g
spesifikasi format, dalam arti bahwa ia menggunakan notasi eksponensial (1.23e+4
) jika angkanya cukup besar atau kecil. Jadi metode ini harus menangkap kasus ini dan menanganinya secara berbeda. Ada beberapa kasus di mana menggunakanf
spesifikasi format malah menyebabkan masalah, seperti mencoba memotong3e-10
ke presisi 28 digit (menghasilkan0.0000000002999999999999999980
), dan saya belum yakin cara terbaik untuk menanganinya.Jika Anda benar - benar bekerja dengan
float
s yang sangat dekat dengan bilangan bulat tetapi sengaja tidak sama dengan bilangan tersebut (seperti 0.29999999999999998 atau 99.959999999999994), ini akan menghasilkan beberapa positif palsu, yaitu bilangan bulat yang tidak ingin dibulatkan. Dalam hal ini, solusinya adalah dengan menentukan presisi tetap.Jumlah digit ketepatan yang digunakan di sini tidak terlalu penting, hanya perlu cukup besar untuk memastikan bahwa pembulatan apa pun yang dilakukan dalam konversi string tidak "menaikkan" nilai ke representasi desimalnya yang bagus. Saya pikir
sys.float_info.dig + n + 2
mungkin cukup dalam semua kasus, tetapi jika tidak2
mungkin harus ditingkatkan, dan tidak ada salahnya untuk melakukannya.Pada versi Python sebelumnya (hingga 2.6, atau 3.0), pemformatan angka floating point jauh lebih kasar, dan secara teratur akan menghasilkan hal-hal seperti
Jika ini adalah situasi Anda, jika Anda tidak ingin menggunakan "bagus" representasi desimal untuk pemotongan, semua dapat Anda lakukan (sejauh yang saya tahu) adalah memilih beberapa jumlah digit, kurang dari representable presisi penuh oleh
float
, dan putaran nomor sebanyak itu sebelum memotongnya. Pilihan tipikal adalah 12,tetapi Anda dapat menyesuaikan ini agar sesuai dengan angka yang Anda gunakan.
1 Yah ... aku berbohong. Secara teknis, Anda dapat menginstruksikan Python untuk mengurai ulang kode sumbernya sendiri dan mengekstrak bagian yang sesuai dengan argumen pertama yang Anda berikan ke fungsi pemotongan. Jika argumen tersebut adalah literal floating-point, Anda bisa memotongnya di sejumlah tempat setelah koma desimal dan mengembalikannya. Namun strategi ini tidak berhasil jika argumennya adalah variabel, yang membuatnya tidak berguna. Hal berikut disajikan hanya untuk hiburan:
Menggeneralisasi ini untuk menangani kasus di mana Anda meneruskan variabel tampaknya seperti penyebab yang hilang, karena Anda harus menelusuri mundur melalui eksekusi program sampai Anda menemukan literal floating-point yang memberi variabel nilainya. Bahkan jika ada. Sebagian besar variabel akan diinisialisasi dari input pengguna atau ekspresi matematika, dalam hal ini representasi biner adalah segalanya.
sumber
applymap()
). Mungkin ada cara untuk membuat seluruh operasi lebih efisien, tapi itu akan menjadi masalah untuk pertanyaan terpisah.Lihat dokumentasi Python tentang tipe standar . Anda harus menggulir sedikit ke bawah untuk mendapatkan fungsi bulat. Pada dasarnya angka kedua menunjukkan berapa banyak tempat desimal untuk membulatkannya.
sumber
Hasilnya
round
adalah float, jadi hati-hati (contohnya dari Python 2.6):Anda akan lebih baik jika menggunakan string yang diformat:
sumber
round(1.23456, 3)
adalah1.235
dan tidak1.2350000000000001
sumber
2
, Anda akan memiliki titik desimal.
di akhir string - menurut saya bukan solusi yang baik.Pada prompt Python 2.7 saya:
>>> int(1.923328437452 * 1000)/1000.0 1.923
sumber
Skrip python sederhana -
sumber
Ini seharusnya berhasil. Ini harus memberi Anda pemotongan yang Anda cari.
sumber
Cara yang benar-benar pythonic untuk melakukannya adalah
atau lebih pendek:
Memperbarui
Biasanya masalahnya bukan pada pemotongan float itu sendiri, tetapi pada penggunaan nomor float yang tidak tepat sebelumnya pembulatan.
Sebagai contoh:
int(0.7*3*100)/100 == 2.09
.Jika Anda dipaksa untuk menggunakan float (katakanlah, Anda mempercepat kode Anda dengan
numba
), lebih baik menggunakan sen sebagai "representasi internal" dari harga: (70*3 == 210
) dan mengalikan / membagi input / output.sumber
int(0.7*3*100)/100 == 2.09
. Kemana perginya 1 sen saya?ImportError: cannot import name 'D'
, saya yakin Anda ingin membuat import bernama no?Begitu banyak jawaban yang diberikan untuk pertanyaan ini benar-benar salah. Mereka membulatkan pelampung (bukan memotong) atau tidak bekerja untuk semua kasus.
Ini adalah hasil teratas Google ketika saya mencari 'Python truncate float', sebuah konsep yang sangat mudah, dan yang pantas mendapatkan jawaban yang lebih baik. Saya setuju dengan Hatchkins bahwa menggunakan
decimal
modul adalah cara pythonic untuk melakukan ini, jadi saya berikan di sini fungsi yang menurut saya menjawab pertanyaan dengan benar, dan yang berfungsi seperti yang diharapkan untuk semua kasus.Sebagai catatan samping, nilai pecahan, secara umum, tidak dapat direpresentasikan secara tepat oleh variabel floating point biner (lihat di sini untuk pembahasannya), itulah mengapa fungsi saya mengembalikan string.
sumber
Saya melakukan sesuatu seperti ini:
sumber
Anda dapat melakukan:
pengujian:
sumber
Jika Anda menyukai sihir matematika, ini berfungsi untuk + lima angka:
sumber
Saat menggunakan pandas df ini berhasil untuk saya
sumber
Hanya ingin menyebutkan bahwa trik lama "make round () with floor ()"
dapat diputar untuk membuat floor () dari round ()
Meskipun kedua aturan ini melanggar bilangan negatif, jadi menggunakannya kurang dari ideal:
sumber
int (16.5); ini akan memberikan nilai integer 16, yaitu trunc, tidak akan bisa menentukan desimal, tapi tebak Anda bisa melakukannya dengan
sumber
Berikut cara mudahnya:
untuk num = 1.923328437452, ini menghasilkan 1.923
sumber
sumber
Fungsi umum dan sederhana untuk digunakan:
sumber
Ada solusi mudah di python 3. Di mana untuk memotong saya mendefinisikan dengan decPlace variabel bantuan untuk membuatnya mudah beradaptasi.
Keluaran:
Semoga membantu.
sumber
sumber
Varian pendek dan mudah
sumber
Sebagian besar jawaban terlalu rumit menurut saya, bagaimana dengan ini?
Cukup memindai indeks '.' dan potong sesuai keinginan (tanpa pembulatan). Ubah string menjadi float sebagai langkah terakhir.
Atau dalam kasus Anda jika Anda mendapatkan float sebagai input dan menginginkan string sebagai output:
sumber
# bagi dan kalikan dengan 10 ** jumlah digit yang diinginkan
sumber
gunakan numpy.round
sumber
Sesuatu yang cukup sederhana agar sesuai dengan pemahaman daftar, tanpa perpustakaan atau dependensi eksternal lainnya. Untuk Python> = 3.6, menulis dengan f-string sangat mudah.
Idenya adalah membiarkan konversi string melakukan pembulatan ke satu tempat lebih banyak dari yang Anda butuhkan dan kemudian memotong digit terakhir.
Tentu saja, ada yang pembulatan terjadi di sini (yaitu untuk digit keempat), tetapi pembulatan di beberapa titik adalah unvoidable. Jika transisi antara pemotongan dan pembulatan relevan, berikut adalah contoh yang sedikit lebih baik:
Bonus: menghilangkan angka nol di sebelah kanan
sumber
Ide inti yang diberikan di sini menurut saya merupakan pendekatan terbaik untuk masalah ini. Sayangnya, ia menerima lebih sedikit suara sementara jawaban selanjutnya yang memiliki lebih banyak suara tidak lengkap (seperti yang diamati di komentar). Semoga penerapan di bawah ini memberikan solusi singkat dan lengkap untuk pemotongan .
yang seharusnya menangani semua kasus sudut yang ditemukan di sini dan di sini .
sumber
Saya juga pemula python dan setelah memanfaatkan beberapa bagian di sini, saya menawarkan dua sen saya
str (int (time.time ())) akan mengambil waktu epoch sebagai int dan mengubahnya menjadi string dan bergabung dengan ... str (datetime.now (). microsecond) [: 3] yang mengembalikan mikrodetik saja, konversikan untuk merangkai dan memotong ke 3 karakter pertama
sumber
sumber
Jika yang Anda maksud saat mencetak, maka berikut ini seharusnya berfungsi:
sumber