Membatasi mengapung ke dua titik desimal

1691

Saya ingin adibulatkan ke 13,95 .

>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999

The roundfungsi tidak bekerja seperti yang saya harapkan.

ShadowRanger
sumber
6
Hmm ... Apakah Anda mencoba mewakili mata uang? Jika demikian, Anda seharusnya tidak menggunakan pelampung untuk dolar. Anda mungkin bisa menggunakan pelampung untuk uang, atau apa pun satuan mata uang terkecil yang Anda coba modelkan terjadi, tetapi praktik terbaik adalah menggunakan representasi desimal, seperti yang disarankan HUAGHAGUAH dalam jawabannya.
SingleNegationElimination
63
Penting untuk tidak mewakili mata uang dalam float. Mengapung tidak tepat. Tetapi jumlah sen atau sen adalah bilangan bulat. Oleh karena itu bilangan bulat adalah cara yang benar untuk mewakili mata uang.
Davoud Taghawi-Nejad
2
@ DavoudTaghawi-Nejad atau lebih tepatnya ... Jenis Desimal
Dasar
17
Saya datang mungkin terlambat di sini, tetapi saya ingin bertanya, apakah pengembang Python menyelesaikan masalah ini? Karena ketika saya melakukan putaran (13.949999999999999, 2), saya hanya mendapatkan 13,95. Saya sudah mencobanya dengan Python 2.7.6, dan 3.4. Berhasil. Tidak yakin apakah 2,7 bahkan ada di sana pada tahun 2009. Mungkin itu hal Python 2.5?
bad_keypoints

Jawaban:

1690

Anda mengalami masalah lama dengan angka floating point yang tidak semua angka dapat diwakili secara tepat. Baris perintah hanya menunjukkan kepada Anda formulir floating point penuh dari memori.

Dengan representasi floating point, versi bulat Anda adalah angka yang sama. Karena komputer adalah biner, mereka menyimpan angka floating point sebagai bilangan bulat dan kemudian membaginya dengan kekuatan dua sehingga 13,95 akan diwakili dengan cara yang sama dengan 125650429603636838 / (2 ** 53).

Angka presisi ganda memiliki 53 bit (16 digit) presisi dan float reguler memiliki 24 bit (8 digit) presisi. Tipe floating point di Python menggunakan presisi ganda untuk menyimpan nilai-nilai.

Sebagai contoh,

>>> 125650429603636838/(2**53)
13.949999999999999

>>> 234042163/(2**24)
13.949999988079071

>>> a = 13.946
>>> print(a)
13.946
>>> print("%.2f" % a)
13.95
>>> round(a,2)
13.949999999999999
>>> print("%.2f" % round(a, 2))
13.95
>>> print("{:.2f}".format(a))
13.95
>>> print("{:.2f}".format(round(a, 2)))
13.95
>>> print("{:.15f}".format(round(a, 2)))
13.949999999999999

Jika Anda hanya mengejar dua tempat desimal (untuk menampilkan nilai mata uang, misalnya), maka Anda memiliki beberapa pilihan yang lebih baik:

  1. Gunakan bilangan bulat dan simpan nilai dalam sen, bukan dolar, lalu bagi dengan 100 untuk dikonversi menjadi dolar.
  2. Atau gunakan nomor titik tetap seperti desimal .
Rex Logan
sumber
27
@Christian Ada perbedaan mendasar antara nilai yang disimpan dan bagaimana Anda menampilkan nilai itu. Memformat output harus memungkinkan Anda untuk menambahkan padding seperti yang diperlukan, serta menambahkan pemisah koma, dll.
Basic
22
Layak disebutkan bahwa "%.2f" % round(a,2)Anda dapat dimasukkan tidak hanya di printf, tetapi juga dalam hal-hal sepertistr()
andilabs
20
mengapa orang selalu mengasumsikan mata uang pada pembulatan floating-point? terkadang Anda hanya ingin bekerja dengan ketelitian yang kurang.
worc
9
@radtek: Anda perlu memahami bahwa nilai biner (tipe float) adalah perkiraan terdekat yang tersedia dari angka desimal (yang Anda kenal sebagai manusia). Tidak ada nilai biner (yang dapat diwakili) seperti 0,245. Itu tidak ada, dan secara matematis tidak bisa ada. Nilai biner yang paling dekat dengan 0,245 sedikit lebih kecil dari 0,245, jadi secara alami itu dibulatkan ke bawah. Demikian juga, tidak ada yang namanya 0,225 dalam biner, tetapi nilai biner yang paling dekat dengan 0,225 sedikit lebih besar dari 0,225, jadi secara alami itu akan bertambah.
John Y
12
@radtek: Anda benar-benar meminta penjelasan. Solusi paling mudah memang untuk digunakan Decimal, dan itu adalah salah satu solusi yang disajikan dalam jawaban ini. Yang lainnya adalah mengubah jumlah Anda menjadi bilangan bulat dan menggunakan bilangan bulat aritmatika. Kedua pendekatan ini juga muncul dalam jawaban dan komentar lainnya.
John Y
586

Ada spesifikasi format baru, Spesifikasi Format Mini-Bahasa String :

Anda dapat melakukan hal yang sama seperti:

"{:.2f}".format(13.949999999999999)

Catatan 1: di atas mengembalikan sebuah string. Untuk mendapatkan float, cukup bungkus dengan float(...):

float("{:.2f}".format(13.949999999999999))

Catatan 2: membungkus dengan float()tidak mengubah apa pun:

>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True
Xolve
sumber
17
untuk menambahkan koma Anda juga dapat '{0:,.2f}'.format(1333.949999999)mencetak '1,333.95'.
Stephen Blum
@ OnurYıldırım: ya, tetapi Anda dapat membungkusnya dengan float(); float("{0:.2f}".format(13.9499999))
Jossef Harush
5
@ JosephseHarush Anda dapat membungkusnya dengan float (), tetapi Anda belum mendapatkan apa-apa. Sekarang Anda memiliki pelampung lagi, dengan semua ketidaktepatan yang sama. 13.9499999999999 dan 13.95 adalah float yang sama.
Ned Batchelder
4
@NedBatchelder: saya setuju bahwa mereka sama, tetapi ini membatasi float ke dua titik desimal :)
Jossef Harush
8
Ngomong-ngomong, karena Python 3.6 kita bisa menggunakan f-string:f"Result is {result:.2f}"
Andrey Semakin
289

Built-in round() berfungsi dengan baik di Python 2.7 atau yang lebih baru.

Contoh:

>>> round(14.22222223, 2)
14.22

Lihatlah dokumentasinya .

anak-anak
sumber
1
Jadi apakah saya mengerti bahwa ini adalah kegagalan Python 2.7? Mengapa fungsi mendasar seperti itu menghasilkan hasil yang berbeda dari v 2.7 ke v 3?
MikeM
tetapi round(2.16, 1)berikan 2.2mengapa python hanya menawarkan truncatefunc
jiamo
Misalnya, jika Anda mencoba membulatkan nilai 2,675 ke dua tempat desimal, Anda mendapatkan ini >>> round(2.675, 2) 2.67 docs.python.org/2/tutorial/floatingpoint.html
hazard89
4
Dari halaman dokumentasi Python 3:Note The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.
Richard Dally
Perhatikan bahwa jika Anda mencoba menggunakan metode ini untuk mencetak angka seperti 1,00000 itu hanya akan mencetak 1,0, terlepas dari berapa banyak titik desimal yang Anda tentukan.
Josh Correia
142

Saya merasa bahwa pendekatan yang paling sederhana adalah menggunakan format()fungsinya.

Sebagai contoh:

a = 13.949999999999999
format(a, '.2f')

13.95

Ini menghasilkan angka float sebagai string dibulatkan ke dua titik desimal.

berikan zukowski
sumber
97

Menggunakan

print"{:.2f}".format(a)

dari pada

print"{0:.2f}".format(a)

Karena yang terakhir dapat menyebabkan kesalahan output ketika mencoba untuk output beberapa variabel (lihat komentar).

Alexey Antonenko
sumber
2
Ini tidak masuk akal. Dua pernyataan yang diberikan berperilaku identik pada Python 2.7, dan hanya pernyataan kedua yang valid pada Python 2.6. (Pernyataan tidak valid dalam Python 3 atau Python <2.6.) Bentuk pertama tidak memiliki keuntungan selain singkatnya.
Mark Dickinson
1
Maksud saya, cetak format "{0: .2f} {0: .2f}" (a, b) akan menyebabkan kesalahan dalam output - itu akan menghasilkan nilai 'a' dua kali. Saat mencetak "{:. 2f} {: .2f}". Format (a, b) akan menampilkan nilai 'a' dan 'b'.
Alexey Antonenko
2
Untuk Python 3, Anda hanya perlu menambahkan tanda kurung cetak (...). Dan di dalam mereka semua yang saya tulis benar.
Alexey Antonenko
"Maksudku, cetak" {0: .2f} {0: .2f} ". Format (a, b) akan menyebabkan kesalahan dalam output". Ah. Nah, itu pernyataan yang sangat berbeda! Mungkin Anda harus mengedit jawaban Anda? (Apa artinya "meningkatkan kesalahan" dalam jawaban saat ini, misalnya? Bisakah Anda memberikan contoh kasus di mana pernyataan kedua menimbulkan pengecualian tetapi yang pertama tidak?)
Mark Dickinson
3
Anda akan mendapatkan format cetak ("{0: .2f} {1: .2f}" (a, b)) jika Anda memiliki dua variabel
Hovo
95

Sebagian besar angka tidak dapat direpresentasikan secara tepat dalam pelampung. Jika Anda ingin membulatkan angka karena itu yang dibutuhkan rumus atau algoritma matematika Anda, maka Anda ingin menggunakan angka bulat. Jika Anda hanya ingin membatasi tampilan hingga presisi tertentu, maka jangan gunakan putaran dan format saja sebagai string itu. (Jika Anda ingin menampilkannya dengan beberapa metode pembulatan alternatif, dan ada banyak, maka Anda perlu mencampur kedua pendekatan tersebut.)

>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'

Dan terakhir, meskipun mungkin yang paling penting, jika Anda ingin matematika yang tepat maka Anda tidak ingin mengapung sama sekali. Contoh biasa adalah berurusan dengan uang dan menyimpan 'sen' sebagai bilangan bulat.


sumber
68

Coba kode di bawah ini:

>>> a = 0.99334
>>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
>>> print a
0.99
ax003d
sumber
Namun berhati-hatilah, nilai a masih merupakan pelampung yang tidak tepat. Lihatlah di sini - repl.it/LJs (Klik "Jalankan Sesi" di bagian atas bagian Kanan).
lifebalance
3
Jika Anda menggunakan pendekatan ini, Anda harus menambahkan 0,5 untuk representasi yang lebih akurat. int (a * 100 + 0.5) / 100.0; Menggunakan math.ceil adalah pilihan lain.
arhuaco
3
@ShashankSawant: Yah, untuk satu hal, jawaban yang disajikan tidak bulat, itu terpotong. Saran untuk menambahkan setengah pada akhirnya akan membulatkan, tetapi kemudian tidak ada manfaat untuk melakukan ini hanya dengan menggunakan roundfungsi di tempat pertama. Untuk hal lain, karena solusi ini masih menggunakan floating point, masalah asli OP tetap ada, bahkan untuk versi "yang diperbaiki" dari "solusi" ini.
John Y
3
-1, ini hanyalah implementasi ulang roundfungsi yang tidak perlu (yang digunakan dalam pertanyaan).
interjay
4
@ interjay yang diperlukan jika round()tidak berfungsi seperti OP yang disebutkan.
Pithikos
57

TLDR;)

Masalah pembulatan input / output telah diselesaikan secara definitif oleh Python 2.7.0 dan 3.1 .

Angka yang dibulatkan dengan benar dapat dikonversi secara bolak-balik:
str -> float() -> repr() -> float() ...atau Decimal -> float -> str -> Decimal
Jenis desimal tidak diperlukan lagi untuk penyimpanan.


(Secara alami, mungkin perlu untuk membulatkan hasil penambahan atau pengurangan angka bulat untuk menghilangkan akumulasi kesalahan bit terakhir. Aritmatika Desimal eksplisit masih bisa berguna, tetapi konversi ke string oleh str() (yaitu dengan membulatkan menjadi 12 digit yang valid) ) cukup baik biasanya jika tidak ada akurasi ekstrim atau tidak ada jumlah ekstrim operasi aritmatika berturut-turut diperlukan.)

Tes tak terbatas :

import random
from decimal import Decimal
for x in iter(random.random, None):           # Verify FOREVER that rounding is fixed :-)
    assert float(repr(x)) == x                # Reversible repr() conversion.
    assert float(Decimal(repr(x))) == x
    assert len(repr(round(x, 10))) <= 12      # Smart decimal places in repr() after round.
    if x >= 0.1:                              # Implicit rounding to 12 significant digits
        assert str(x) == repr(round(x, 12))   # by str() is good enough for small errors.
        y = 1000 * x                             # Decimal type is excessive for shopping
        assert str(y) == repr(round(y, 12 - 3))  # in a supermaket with Python 2.7+ :-)

Dokumentasi

Lihat catatan Rilis Python 2.7 - Perubahan Bahasa Lainnya paragraf keempat:

Konversi antara angka floating-point dan string sekarang dibulatkan dengan benar di sebagian besar platform. Konversi ini terjadi di banyak tempat berbeda: str () pada float dan bilangan kompleks; konstruktor apung dan kompleks; pemformatan numerik; serialisasi dan de-serialisasi pelampung dan bilangan kompleks menggunakan marshal, pickledan jsonmodul; parsing float dan imajiner literal dalam kode Python; dan konversi Desimal ke float.

Terkait dengan ini, repr () dari angka floating-point x sekarang mengembalikan hasil berdasarkan string desimal terpendek yang dijamin untuk dibulatkan kembali ke x di bawah pembulatan yang benar (dengan mode pembulatan setengah-ke-even). Sebelumnya memberi string berdasarkan pembulatan x hingga 17 angka desimal.

Masalah terkait


Informasi lebih lanjut: Pemformatan floatsebelum Python 2.7 mirip dengan saat ini numpy.float64. Kedua jenis menggunakan 64 bit IEEE 754 ganda yang sama presisi dengan mantissa 52 bit. Perbedaan besar adalah yang diformat sehingga setiap digit penting; urutannya tanpa celah dan konversi dapat dibalik. Cukup: Jika Anda mungkin memiliki nomor numpy.float64, ubah nomor itu menjadi float normal untuk diformat untuk manusia, bukan untuk pengolah angka, jika tidak, tidak ada lagi yang diperlukan dengan Python 2.7+.np.float64.__repr__ sering diformat dengan angka desimal yang berlebihan sehingga tidak ada bit yang bisa hilang, tetapi tidak ada nomor IEEE 754 yang valid ada antara 13,949999999999999 dan 13.950000000000001. Hasilnya tidak bagus dan konversi repr(float(number_as_string))tidak reversibel dengan numpy. Di samping itu:float.__repr__

hynekcer
sumber
Mengapa downvoted? Pertanyaannya adalah tentang Python float(presisi ganda) dan normal round, bukan tentang numpy.double dan konversi ke string. Pembulatan Python benar-benar tidak bisa dilakukan lebih baik daripada di Python 2.7. Sebagian besar jawaban telah ditulis sebelum 2.7, tetapi mereka sudah usang, meskipun awalnya sangat bagus. Inilah alasan jawaban saya.
hynekcer
53 bit ketika Anda memasukkan "bit tersembunyi", yang secara implisit 1, kecuali selama "aliran bawah bertahap".
Rick James
Ini bukan kesalahan bulat, itu kesalahan tampilan.
Rick James
Ya, itu sudah terkenal. Namun saya kehilangan konteks jika Anda keberatan dengan sesuatu dalam Python 2.7 Rilis catatan atau dalam teks saya atau tidak sama sekali. Lebih rumit daripada yang diperlukan tujuan dari pertanyaan ini. Harus ditambahkan bahwa juga konversi dari string ke float telah diperbaiki di Python 2.7 karena pembulatan bug pada chip Intel 32-bit tertentu dan bahwa fungsi "Round () juga sekarang dibulatkan dengan benar." ( Catatan rilis - 3,1 fitur backported ke 2,7 ). Bisakah kamu setuju?
hynekcer
1
Ups, itu a*bvs b*a. Terima kasih atas tautannya - Nostalgia.
Rick James
52

Dengan Python <3 (mis. 2.6 atau 2.7), ada dua cara untuk melakukannya.

# Option one 
older_method_string = "%.9f" % numvar

# Option two (note ':' before the '.9f')
newer_method_string = "{:.9f}".format(numvar)

Tetapi perhatikan bahwa untuk versi Python di atas 3 (mis. 3.2 atau 3.3), opsi dua lebih disukai .

Untuk informasi lebih lanjut tentang opsi dua, saya sarankan tautan ini pada pemformatan string dari dokumentasi Python .

Dan untuk informasi lebih lanjut tentang opsi satu, tautan ini akan cukup dan memiliki informasi tentang berbagai flag .

Referensi: Konversi angka floating point ke presisi tertentu, dan kemudian salin ke string

AJ
sumber
Bagaimana Anda mewakili bilangan bulat? Jika saya menggunakan format "{i3}". (Numvar) saya mendapatkan kesalahan.
skytux
Inilah yang saya maksud: Jika numvar=12.456, maka "{:.2f}".format(numvar)menghasilkan 12.46tetapi "{:2i}".format(numvar)memberikan kesalahan dan saya mengharapkan 12.
skytux
50

Anda dapat mengubah format output:

>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95
Greg Hewgill
sumber
47

Tidak ada yang tampaknya telah menyebutkannya, jadi izinkan saya memberi contoh dalam format f-string / template-string Python 3.6, yang menurut saya sangat rapi:

>>> f'{a:.2f}'

Ini bekerja dengan baik dengan contoh yang lebih panjang juga, dengan operator dan tidak perlu parens:

>>> print(f'Completed in {time.time() - start:.2f}s')
Matt Fletcher
sumber
39

Anda dapat menggunakan operator format untuk membulatkan nilai hingga 2 tempat desimal dengan python:

print(format(14.4499923, '.2f')) // output is 14.45
Asad Manzoor
sumber
4
Ini mengembalikan string
Jemshit Iskenderov
29

Dengan Python 2.7:

a = 13.949999999999999
output = float("%0.2f"%a)
print output
Shashank Singh
sumber
1
Ini sama sekali tidak membantu. outputmemiliki yang sama persis nilai seperti a, sehingga Anda mungkin juga telah menulis print abukan print outputdi baris terakhir.
Mark Dickinson
@MarkDickinson Bisakah Anda mencoba lagi. Karena ini berjalan seperti yang diharapkan di kompiler saya.
Shashank Singh
1
Anda kehilangan poin saya. Ya, kode Anda dicetak 13.95. Namun demikian print a, untuk nilai khusus ini a, dalam Python 2.7, jadi tidak terlalu jelas apa gunanya langkah pemformatan.
Mark Dickinson
@ MarkDickinson saya telah mengedit kode. Saya setuju bahwa 'print a' memang mencetak nilai yang sama dengan "print output". Tetapi jika Anda membandingkan "a == output", hasilnya akan menjadi "False" karena langkah pemformatan mengakhiri nilai mengambang "a" menjadi dua titik desimal.
Shashank Singh
1
Apakah Anda benar-benar mencoba a == outputkode yang Anda perlihatkan? Itu memberi Trueuntuk saya, dan saya curiga itu juga untuk Anda.
Mark Dickinson
22

Tutorial Python memiliki lampiran yang disebut Floating Point Arithmetic: Issues and Limitations . Membacanya. Ini menjelaskan apa yang terjadi dan mengapa Python melakukan yang terbaik. Ia bahkan memiliki contoh yang cocok dengan milik Anda. Biarkan saya kutip sedikit:

>>> 0.1
0.10000000000000001

Anda mungkin tergoda untuk menggunakan round() fungsi ini untuk memotongnya kembali ke satu digit yang Anda harapkan. Tapi itu tidak ada bedanya:

>>> round(0.1, 1)
0.10000000000000001

Masalahnya adalah bahwa nilai floating-point biner yang disimpan “0.1” sudah merupakan perkiraan biner terbaik 1/10, jadi mencoba membulatkannya lagi tidak bisa membuatnya lebih baik: itu sudah sebaik yang didapat.

Konsekuensi lain adalah bahwa karena 0.1 tidak tepat 1/10, menjumlahkan sepuluh nilai 0.1mungkin tidak menghasilkan dengan tepat 1.0, baik:

>>> sum = 0.0
>>> for i in range(10):
...     sum += 0.1
...
>>> sum
0.99999999999999989

Salah satu alternatif dan solusi untuk masalah Anda adalah menggunakan decimalmodul.

nosklo
sumber
18

Seperti yang ditunjukkan @Matt, Python 3.6 menyediakan f-string , dan mereka juga dapat menggunakan parameter bersarang :

value = 2.34558
precision = 2
width = 4

print(f'result: {value:{width}.{precision}f}')

yang akan ditampilkan result: 2.35

toto_tico
sumber
13

Itu melakukan persis apa yang Anda perintahkan dan lakukan dengan benar. Baca lebih lanjut tentang kebingungan floating point dan mungkin coba objek desimal sebagai gantinya.

HUAGHAGUAH
sumber
11

Gunakan kombinasi objek Decimal dan metode round ().

Python 3.7.3
>>> from decimal import Decimal
>>> d1 = Decimal (13.949999999999999) # define a Decimal
>>> d1 
Decimal('13.949999999999999289457264239899814128875732421875')
>>> d2 = round(d1, 2) # round to 2 decimals
>>> d2
Decimal('13.95')
Jonathan L.
sumber
7

Untuk memperbaiki titik mengambang dalam bahasa tipe-dinamis seperti Python dan JavaScript, saya menggunakan teknik ini

# For example:
a = 70000
b = 0.14
c = a * b

print c # Prints 980.0000000002
# Try to fix
c = int(c * 10000)/100000
print c # Prints 980

Anda juga dapat menggunakan Desimal sebagai berikut:

from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
# Results in 6 precision -> Decimal('0.142857')

getcontext().prec = 28
Decimal(1) / Decimal(7)
# Results in 28 precision -> Decimal('0.1428571428571428571428571429')
Siamand
sumber
1
getcontext().prec = 6berfungsi hanya untuk lingkup fungsi atau semua tempat?
Julio Marins
1
Konteks adalah lingkungan untuk operasi aritmatika. Mereka mengatur presisi, menetapkan aturan untuk pembulatan, menentukan sinyal mana yang diperlakukan sebagai pengecualian, dan membatasi rentang eksponen. Setiap utas memiliki konteksnya sendiri saat ini @JulioMarins
Siamand
7
from decimal import Decimal


def round_float(v, ndigits=2, rt_str=False):
    d = Decimal(v)
    v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
    if rt_str:
        return v_str
    return Decimal(v_str)

Hasil:

Python 3.6.1 (default, Dec 11 2018, 17:41:10)
>>> round_float(3.1415926)
Decimal('3.14')
>>> round_float(3.1445926)
Decimal('3.14')
>>> round_float(3.1455926)
Decimal('3.15')
>>> round_float(3.1455926, rt_str=True)
'3.15'
>>> str(round_float(3.1455926))
'3.15'
menangis
sumber
6
orig_float = 232569 / 16000.0

14.5355625

short_float = float("{:.2f}".format(orig_float)) 

14.54

MikeL
sumber
5

Bagaimana dengan fungsi lambda seperti ini:

arred = lambda x,n : x*(10**n)//1/(10**n)

Dengan cara ini Anda bisa melakukan:

arred(3.141591657,2)

dan dapatkan

3.14
Gustavo Mirapalheta
sumber
4

Sederhana seperti 1,2,3:

  1. gunakan modul desimal untuk aritmatika floating point desimal yang dibulatkan dengan benar:

    d = Desimal (10000000.0000009)

untuk mencapai pembulatan:

   d.quantize(Decimal('0.01'))

akan menghasilkan dengan Decimal('10000000.00')

  1. buat KERING di atas:
    def round_decimal(number, exponent='0.01'):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(exponent))

ATAU

    def round_decimal(number, decimal_places=2):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(10) ** -decimal_places)
  1. jawab jawaban ini :)

PS: kritik orang lain: format tidak pembulatan.

Sławomir Lenart
sumber
2

Untuk membulatkan angka ke resolusi, cara terbaik adalah yang berikut, yang dapat bekerja dengan resolusi apa pun (0,01 untuk dua desimal atau bahkan langkah lain):

>>> import numpy as np
>>> value = 13.949999999999999
>>> resolution = 0.01
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
13.95

>>> resolution = 0.5
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
14.0
iblasi
sumber
tidak bekerja untuk saya di python 3.4.3 dan 1.9.1 numpy? >>> impor numpy as np >>> res = 0,01 >>> value = 0.184 >>> np.round (nilai / res) * res 0.17999999999999999
szeitlin
1
Mencari dokumentasi saya melihat masalah berasal dari numpy.roundakurasi / presisi. Jadi itu perlu mendefinisikannya sebagai int sebelum perkalian dengan resolusi. Saya memperbarui kode. Terima kasih untuk itu!
iblasi
Satu-satunya yang diperlukan adalah untuk mengubah numpy.float64hasil np.round menjadi floatatau hanya menggunakan round(value, 2). Tidak ada nomor IEEE 754 yang valid antara 13.949999999999999 (= 1395 / 100.) dan 3.95000000000000001 (= 1395 * .01). Mengapa Anda berpikir bahwa metode Anda adalah yang terbaik? Nilai asli 13.949999999999999289 (= value = round (value, 2)) bahkan lebih tepat daripada 13.9500000000000000178 Anda (dicetak oleh np.float96). Info lebih lanjut juga untuk numpy sekarang ditambahkan ke jawaban saya bahwa Anda mungkin downvoted karena kesalahan. Awalnya itu bukan tentang numpy.
hynekcer
@hynekcer Saya tidak berpikir bahwa jawaban saya adalah yang terbaik. Hanya ingin menambahkan contoh float batas ke n desimal tetapi yang terdekat dari resolusi yang ditentukan. Saya memeriksa seperti yang Anda katakan, bahwa alih-alih intAnda juga dapat menggunakan floatcontoh @szeitlin. Terima kasih atas komentar ekstra Anda. (Maaf tapi saya tidak
menurunkan suara
Menambahkan ketergantungan baru untuk pemrosesan numerik (panda) adalah "cara terbaik"?
Hejazzman
1

lambda x, n: int (x * 10 n + .5) / 10 n telah bekerja untuk saya selama bertahun- tahun dalam banyak bahasa.

Ray Tayek
sumber
-13

Metode yang saya gunakan adalah mengiris string. Ini relatif cepat dan sederhana.

Pertama, ubah float menjadi string, pilih panjang yang Anda inginkan.

float = str(float)[:5]

Pada baris tunggal di atas, kami telah mengonversi nilai menjadi string, lalu menyimpan string hanya hingga empat digit pertama atau karakter (inklusif).

Semoga itu bisa membantu!

tdh
sumber
2
Tolong jangan posting jawaban yang identik untuk beberapa pertanyaan.
vaultah
18
WOW ... tdh ... Tolong jangan pernah membuat perangkat lunak akuntansi ... Apa yang terjadi jika angkanya 113,94 ?? ini akan menghasilkan 113,9 ... meninggalkan 0,04 hilang .... Juga ini sudah memiliki jawaban dari lebih dari 5 tahun yang lalu ....
Angry 84