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

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

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

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          

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

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

2
def rounding(float,precision)
    return ((float * 10**precision).round.to_f) / (10**precision)
end


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


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.