Pembulatan mengapung di Ruby

150

Saya mengalami masalah pembulatan. Saya memiliki float, yang ingin saya bulatkan ke seratus desimal. Namun, saya hanya bisa menggunakan .roundyang pada dasarnya mengubahnya menjadi int, artinya 2.34.round # => 2. Adakah cara efek sederhana untuk melakukan sesuatu seperti2.3465 # => 2.35

pengguna211662
sumber

Jawaban:

181

Saat menampilkan, Anda dapat menggunakan (misalnya)

>> '%.2f' % 2.3465
=> "2.35"

Jika Anda ingin menyimpannya bulat, Anda bisa menggunakannya

>> (2.3465*100).round / 100.0
=> 2.35
Peter
sumber
2
Terima kasih. Saya tidak menyadari sprintf akan mengurus pembulatan untuk saya. sprintf '%.2f', 2.3465juga berfungsi.
Noah Sussman
66
value.round (2) lebih baik daripada solusi ini
Kit Ho
12
Ingat itu 2.3000.round(2) => 2.3dan sprintf '%.2f', 2.300 => 2.30. Menurut pendapat saya ini adalah cacat round (), atau seharusnya memiliki opsi untuk menjaga nol trailing.
Excalibur
14
@Exiburibur 2.3000.round(2)adalah angka, bukan string. Tidak mungkin nomornya 2.3berbeda 2.30, jadi tidak ada cara untuk memiliki opsi untuk melestarikan angka nol. Anda dapat membuat kelas number_with_significance Anda sendiri tetapi kemudian kami sudah memiliki string.
Roobie Nuby
6
Perhatikan bahwa meskipun ini tidak bekerja untuk dua desimal, ada cacat di '%.3f' % 1.2345(3 desimal tempat, tidak 2), namun !! Sama sprintfjuga. Awas. Itu akan kembali => 1.234 tidak => 1.235 seperti yang diharapkan kebanyakan (iow, setelah desimal ke-2, putaran sprintf 5 turun dan hanya putaran 6 ke atas). Itu sebabnya komentar Kit Ho di atas memiliki 25+ upvotes. Lebih aman untuk digunakan, '%.3f' % 1.2345.round(3)sehingga angka dibulatkan dengan benar .roundterlebih dahulu, lalu diformat (dengan trailing nol, jika perlu).
likethesky
392

Berikan argumen ke putaran yang berisi jumlah tempat desimal untuk dibulatkan

>> 2.3465.round
=> 2
>> 2.3465.round(2)
=> 2.35
>> 2.3465.round(3)
=> 2.347
Steve Weet
sumber
8
Ini akan tampak lebih masuk akal daripada mengalikan, membulatkan dan membagi. +1
Mark Embling
3
Hmm metode ini sepertinya tidak ada di ruby ​​1.8.7. Mungkin di 1.9?
Brian Armstrong
2
@ Brian. Ini jelas di 1.9 dan juga di rails (yang ditandai dengan pertanyaan ini)
Steve Weet
3
Metode putaran Ruby 1.8.7 tidak memiliki kemampuan ini, menambahkan parameter pembulatan desimal adalah kemampuan 1.9
bobmagoo
1
Perhatikan bahwa Anda tidak mendapatkan angka nol dengan ini, jadi 1.1.round(2)=> 1.1tidak1.10
NotAnAmbiTurner
9

Anda dapat menggunakan ini untuk pembulatan ke penjara ..

//to_f is for float

salary= 2921.9121
puts salary.to_f.round(2) // to 2 decimal place                   

puts salary.to_f.round() // to 3 decimal place          
roti teknologi
sumber
7

Anda dapat menambahkan metode di Float Class, saya belajar ini dari stackoverflow:

class Float
    def precision(p)
        # Make sure the precision level is actually an integer and > 0
        raise ArgumentError, "#{p} is an invalid precision level. Valid ranges are integers > 0." unless p.class == Fixnum or p < 0
        # Special case for 0 precision so it returns a Fixnum and thus doesn't have a trailing .0
        return self.round if p == 0
        # Standard case  
        return (self * 10**p).round.to_f / 10**p
    end
end
Albert Català
sumber
3

Anda juga bisa memberikan angka negatif sebagai argumen roundmetode untuk membulatkan ke kelipatan terdekat dari 10, 100 dan seterusnya.

# Round to the nearest multiple of 10. 
12.3453.round(-1)       # Output: 10

# Round to the nearest multiple of 100. 
124.3453.round(-2)      # Output: 100
BrunoFacca
sumber
2
def rounding(float,precision)
    return ((float * 10**precision).round.to_f) / (10**precision)
end
PeteJLeonard
sumber
2

bagaimana (2.3465*100).round()/100.0?

lalukerja
sumber
1

Jika Anda hanya perlu menampilkannya, saya akan menggunakan bantuan number_with_precision . Jika Anda membutuhkannya di tempat lain saya akan menggunakan, seperti yang ditunjukkan Steve Weet, roundmetode

Fer
sumber
1
Perhatikan bahwa number_with_precisionini adalah metode Rails-only.
Smar
0

Untuk ruby ​​1.8.7 Anda bisa menambahkan yang berikut ini ke kode Anda:

class Float
    alias oldround:round
    def round(precision = nil)
        if precision.nil?
            return self
        else
            return ((self * 10**precision).oldround.to_f) / (10**precision)
        end 
    end 
end
Robert
sumber