Saya perlu membulatkan float untuk ditampilkan di UI. Misalnya, untuk satu tokoh penting:
1234 -> 1000
0,12 -> 0,1
0,012 -> 0,01
0,062 -> 0,06
6253 -> 6000
1999 -> 2000
Apakah ada cara yang bagus untuk melakukan ini menggunakan perpustakaan Python, atau apakah saya harus menulisnya sendiri?
Jawaban:
Anda dapat menggunakan angka negatif untuk membulatkan bilangan bulat:
Jadi, jika Anda hanya membutuhkan digit paling signifikan:
Anda mungkin harus berhati-hati mengubah float ke integer jika lebih besar dari 1.
sumber
log10
adalah satu-satunya cara yang tepat untuk menentukan cara membulatkannya.log10(abs(x))
, jika tidak, angka negatif akan gagal (Dan memperlakukanx == 0
secara terpisah tentu saja)round_to_n = lambda x, n: x if x == 0 else round(x, -int(math.floor(math.log10(abs(x)))) + (n - 1))
melindungix==0
danx<0
Terima kasih @RoyHyunjinHan dan @TobiasKienzler. Tidak dilindungi terhadap undefined seperti math.inf, atau sampah seperti Tidak ada dll% g dalam pemformatan string akan memformat float dibulatkan ke beberapa angka penting. Terkadang akan menggunakan notasi ilmiah 'e', jadi konversikan string bulat kembali ke float lalu melalui pemformatan string% s.
sumber
0.075
untuk0.08
. Ia mengembalikannya0.07
.round_sig = lambda f,p: float(('%.' + str(p) + 'e') % f)
memungkinkan Anda untuk menyesuaikan jumlah digit signifikan!Jika Anda ingin memiliki selain 1 desimal yang signifikan (jika tidak sama dengan Evgeny):
sumber
0.075
untuk0.08
. Ia mengembalikannya0.07
.round
. docs.python.org/2/tutorial/floatingpoint.html#tut-fp-issuesSolusi ini berbeda dari yang lain karena:
Untuk angka
n
signifikan yang sewenang-wenang , Anda dapat menggunakan:Uji:
Catatan : dengan solusi ini, tidak mungkin untuk mengadaptasi jumlah angka signifikan secara dinamis dari input karena tidak ada cara standar untuk membedakan angka dengan angka trailing zero yang berbeda (
3.14 == 3.1400
). Jika Anda perlu melakukannya, maka fungsi-fungsi non-standar seperti yang disediakan dalam paket to-precision diperlukan.sumber
:g
formatter yang mempertahankan bilangan bulat.2000.0
menyarankan 5 digit signifikan, sehingga harus melalui{:g}
lagi.) Secara umum, bilangan bulat dengan nol trailing adalah ambigu berkaitan dengan angka signifikan, kecuali beberapa teknik (seperti overline di atas signifikan terakhir) digunakan.Saya telah membuat paket dengan presisi yang melakukan apa yang Anda inginkan. Ini memungkinkan Anda untuk memberikan angka Anda angka yang lebih atau kurang signifikan.
Ini juga menghasilkan notasi standar, ilmiah, dan teknik dengan sejumlah angka penting yang ditentukan.
Dalam jawaban yang diterima ada garis
Itu sebenarnya menentukan 8 buah ara. Untuk angka 1234243 perpustakaan saya hanya menampilkan satu angka penting:
Itu juga akan membulatkan angka signifikan terakhir dan secara otomatis dapat memilih notasi apa yang akan digunakan jika notasi tidak ditentukan:
sumber
lambda x: to_precision(x, 2)
Untuk membulatkan bilangan bulat ke 1 angka penting, ide dasarnya adalah mengonversinya menjadi titik mengambang dengan 1 digit sebelum titik dan membulatkannya, lalu mengonversinya kembali ke ukuran bilangan bulat aslinya.
Untuk melakukan ini kita perlu mengetahui kekuatan terbesar 10 lebih kecil dari integer. Kita dapat menggunakan lantai fungsi log 10 untuk ini.
sumber
Untuk langsung menjawab pertanyaan, inilah versi saya menggunakan penamaan dari fungsi R :
Alasan utama saya untuk memposting jawaban ini adalah komentar yang mengeluh bahwa "0,075" membulatkan menjadi 0,07 daripada 0,08. Hal ini disebabkan, sebagaimana ditunjukkan oleh "Novice C", ke kombinasi aritmatika titik apung yang memiliki presisi hingga dan representasi basis-2 . Angka terdekat ke 0,075 yang sebenarnya bisa direpresentasikan sedikit lebih kecil, maka pembulatan keluar berbeda dari yang mungkin Anda harapkan secara naif.
Perhatikan juga bahwa ini berlaku untuk setiap penggunaan aritmatika titik apung non-desimal, misalnya C dan Java keduanya memiliki masalah yang sama.
Untuk menunjukkan lebih detail, kami meminta Python untuk memformat angka dalam format "hex":
yang memberi kami:
0x1.3333333333333p-4
. Alasan untuk melakukan ini adalah bahwa representasi desimal normal sering melibatkan pembulatan dan karenanya bukan bagaimana komputer benar-benar "melihat" nomor tersebut. Jika Anda tidak terbiasa dengan format ini, beberapa referensi yang bermanfaat adalah dokumen Python dan standar C .Untuk menunjukkan bagaimana angka-angka ini bekerja sedikit, kita dapat kembali ke titik awal dengan melakukan:
yang harus dicetak
0.075
.16**13
karena ada 13 digit heksadesimal setelah titik desimal, dan2**-4
karena eksponen hex adalah basis-2.Sekarang kami memiliki beberapa gagasan tentang bagaimana float diwakili, kami dapat menggunakan
decimal
modul untuk memberi kami lebih presisi, menunjukkan kepada kami apa yang terjadi:memberi:
0.07499999999999999722444243844
dan semoga menjelaskan mengaparound(0.075, 2)
dievaluasi0.07
sumber
0.074999999999999999
, apa yang Anda harapkan untuk mendapatkan dalam kasus itu?Mudah-mudahan mengambil yang terbaik dari semua jawaban di atas (dikurangi bisa menjadikannya sebagai lambda satu baris;)). Belum dieksplorasi, silakan edit jawaban ini:
sumber
Saya memodifikasi solusi indgar untuk menangani angka negatif dan angka kecil (termasuk nol).
sumber
x == 0
? Jika Anda menyukai one-liner, adilreturn 0 if x==0 else round(...)
.0.970 == 0.97
). Saya pikir Anda bisa menggunakan beberapa solusi cetak lainnya sepertif'{round_sig(0.9701, sig=3):0.3f}'
jika Anda ingin nol dicetak.Jika Anda ingin membulatkan tanpa melibatkan string, tautan yang saya temukan terkubur dalam komentar di atas:
http://code.activestate.com/lists/python-tutor/70739/
menurut saya yang terbaik. Kemudian ketika Anda mencetak dengan deskriptor pemformatan string apa pun, Anda mendapatkan hasil yang masuk akal, dan Anda bisa menggunakan representasi numerik untuk keperluan perhitungan lainnya.
Kode pada tautan adalah tiga baris: def, doc, dan return. Ini memiliki bug: Anda perlu memeriksa logaritma yang meledak. Itu mudah. Bandingkan input dengan
sys.float_info.min
. Solusi lengkapnya adalah:Ini berfungsi untuk nilai numerik skalar apa pun, dan n bisa menjadi
float
jika Anda perlu mengubah respons karena alasan tertentu. Anda benar-benar dapat mendorong batas ke:tanpa memprovokasi kesalahan, jika karena alasan tertentu Anda bekerja dengan nilai sangat kecil.
sumber
Saya tidak bisa memikirkan apa pun yang bisa menangani ini di luar kotak. Tapi itu ditangani dengan cukup baik untuk angka floating point.
Bilangan bulat lebih rumit. Mereka tidak disimpan sebagai basis 10 dalam memori, jadi tempat yang signifikan bukanlah hal yang wajar untuk dilakukan. Ini cukup sepele untuk diterapkan begitu mereka adalah string.
Atau untuk bilangan bulat:
Jika Anda ingin membuat fungsi yang menangani angka apa pun, preferensi saya adalah mengonversikan keduanya menjadi string dan mencari tempat desimal untuk memutuskan apa yang harus dilakukan:
Pilihan lain adalah memeriksa jenisnya. Ini akan jauh kurang fleksibel, dan mungkin tidak akan bermain bagus dengan nomor lain seperti
Decimal
objek:sumber
Jawaban yang diposting adalah yang terbaik yang tersedia ketika diberikan, tetapi memiliki sejumlah keterbatasan dan tidak menghasilkan angka signifikan yang benar secara teknis.
numpy.format_float_positional mendukung perilaku yang diinginkan secara langsung. Fragmen berikut mengembalikan float yang
x
diformat menjadi 4 angka penting, dengan notasi ilmiah ditekan.sumber
print(*[''.join([np.format_float_positional(.01*a*n,precision=2,unique=False,fractional=False,trim='k',pad_right=5) for a in [.99, .999, 1.001]]) for n in [8,9,10,11,12,19,20,21]],sep='\n')
. Saya tidak memeriksa Dragon4 sendiri.Saya juga mengalami hal ini tetapi saya membutuhkan kontrol atas jenis pembulatan. Jadi, saya menulis fungsi cepat (lihat kode di bawah) yang dapat mengambil nilai, jenis pembulatan, dan angka-angka penting yang diinginkan.
sumber
Menggunakan format python 2.6+ gaya baru (karena%-style sudah usang):
Dalam python 2.7+ Anda dapat menghilangkan
0
s terkemuka .sumber
Fungsi ini melakukan putaran normal jika jumlahnya lebih besar dari 10 ** (- decimal_positions), jika tidak menambahkan lebih banyak desimal hingga jumlah posisi desimal yang berarti tercapai:
Semoga ini bisa membantu.
sumber
https://stackoverflow.com/users/1391441/gabriel , apakah yang berikut ini menanggapi kekhawatiran Anda tentang rnd (.075, 1)? Peringatan: mengembalikan nilai sebagai pelampung
sumber
Ini mengembalikan string, sehingga hasil tanpa bagian fraksional, dan nilai-nilai kecil yang akan muncul dalam notasi E ditampilkan dengan benar:
sumber
Diberikan pertanyaan sehingga dijawab dengan seksama mengapa tidak menambahkan yang lain
Ini cocok dengan estetika saya sedikit lebih baik, meskipun banyak di atas sebanding
Ini berfungsi untuk bilangan individual dan array numpy, dan harus berfungsi baik untuk bilangan negatif.
Ada satu langkah tambahan yang mungkin kita tambahkan - np.round () mengembalikan angka desimal bahkan jika bulat adalah bilangan bulat (yaitu untuk significantFigures = 2 kita mungkin berharap untuk mendapatkan kembali -460 tetapi sebaliknya kita mendapatkan -460.0). Kami dapat menambahkan langkah ini untuk memperbaiki itu:
Sayangnya, langkah terakhir ini tidak akan berhasil untuk array angka - Saya akan menyerahkan kepada Anda pembaca yang budiman untuk mencari tahu jika Anda perlu.
sumber
The sigfig paket / selimut perpustakaan ini. Setelah menginstal Anda dapat melakukan hal berikut:
sumber
sumber