2011-12-21 84 views
8

Tôi đang sử dụng Ruby 1.8.7 và Rails 2.3.5.Cách đếm số chữ số thập phân trong Float?

Nếu tôi có float như 12.525, làm cách nào để có được số chữ số ở vị trí thập phân? Trong trường hợp này tôi mong đợi để có được một '3' trở lại.

Trả lời

9

Đây là một cách tiếp cận rất đơn giản. Theo dõi số lần bạn phải bội số bằng 10 trước khi nó bằng số nguyên tương đương của nó:

def decimals(a) 
    num = 0 
    while(a != a.to_i) 
     num += 1 
     a *= 10 
    end 
    num 
end 

decimals(1.234) # -> 3 
decimals(10/3.0) # -> 16 
+1

Khá một giải pháp thanh lịch! – Linuxios

+0

Cảm ơn, tôi bị kẹt trong tệp trợ giúp ứng dụng của tôi. Rất vui khi có được gọi khi cần. – Reno

+1

Còn (1/3) thì sao? – MrYoshiji

2

Giống như này:

theFloat.to_s.split(".")[1].length 

Nó không phải là rất đẹp, nhưng bạn có thể chèn nó như là một phương pháp để Float:

class Float 
    def decimalPlaces 
     self.to_s.split(".")[1].length 
    end 
end 
+0

Cách tiếp cận này cho tôi 14 (10/3,0) nhưng câu trả lời của tôi cho 16. Tôi nghĩ rằng số thập phân lặp lại sẽ là vấn đề bất kể bạn tiếp cận nó như thế nào. –

+0

Vâng, đó là lẻ ... Tôi cần phải sử dụng IRB! – Linuxios

+0

Mỗi cách tiếp cận phụ thuộc vào những thứ khác nhau, vì vậy các câu trả lời khác nhau không quá ngạc nhiên. –

17

Something như thế, tôi đoán:

n = 12.525 
n.to_s.split('.').last.size 
+2

Lưu ý rằng điều này sẽ trả về 1 nếu 'n' là một số nguyên, khi bạn có thể muốn một số không. Điều này vấp ngã tôi khi tôi đã trộn lẫn số nguyên và phao nổi. – Barry

+3

'return 0 nếu không num.to_s.include? '.'' – laffuste

0

Bạn có thể trừ sàn và sau đó chỉ đếm số ký tự còn lại?

(12,525 - (12.525.floor)) to_s.length-2 => 3

chỉnh sửa:. Nope doesnt làm việc này cho một loạt các lý do, tiêu cực và 0,99999 vấn đề

+0

Chỉ hoạt động ở 1.8. Hãy thử với 1.9. –

15

Bạn nên rất cẩn thận với những gì bạn muốn. Floating point numbers là tuyệt vời cho mục đích khoa học và chủ yếu là làm việc cho sử dụng hàng ngày, nhưng họ rơi ngoài khá xấu khi bạn muốn biết một cái gì đó như "bao nhiêu chữ số qua thập phân" - nếu chỉ vì họ có about 16 digits total, không phải tất cả chính xác dữ liệu để tính toán của bạn. (Hoặc, một số thư viện thực sự có thể vứt bỏ dữ liệu chính xác về phía cuối của số khi định dạng số cho đầu ra, với lý do là "số làm tròn thân thiện hơn", trong khi thường đúng, có nghĩa là nó có thể nguy hiểm một chút . dựa vào định dạng đầu ra)

Nếu bạn có thể thay thế các số dấu chấm động tiêu chuẩn với lớp BigDecimal để cung cấp tùy ý chính xác số dấu chấm động, sau đó bạn có thể kiểm tra "thô" số:

> require 'bigdecimal' 
=> true 
> def digits_after_decimal_point(f) 
> sign, digits, base, exponent = f.split 
> return digits.length - exponent 
> end 
> l = %w{1.0, 1.1, 1000000000.1, 1.0000000001} 
=> ["1.0,", "1.1,", "1000000000.1,", "1.0000000001"] 
> list = l.map { |n| BigDecimal(n) } 
=> [#<BigDecimal:7f7a56aa8f70,'0.1E1',9(18)>, #<BigDecimal:7f7a56aa8ef8,'0.11E1',18(18)>, #<BigDecimal:7f7a56aa8ea8,'0.1000000000 1E10',27(27)>, #<BigDecimal:7f7a56aa8e58,'0.1000000000 1E1',27(27)>] 
> list.map { |i| digits_after_decimal_point(i) } 
=> [0, 1, 1, 10] 

trong số Tất nhiên, nếu di chuyển đến BigDecimal làm cho ứng dụng của bạn quá chậm hoặc quá mạnh mẽ với những gì bạn cần, điều này có thể làm phức tạp quá mức mã của bạn vì không có lợi ích thực sự. Bạn sẽ phải quyết định điều gì là quan trọng nhất đối với ứng dụng của bạn.

+2

TAKE CARE: Giá trị 0 trả về 1 (phải là 0) và giá trị 10 trả về -1. – reto

+0

@reto, bắt thú vị. Cảm ơn. – sarnold

+0

Nếu bạn đã có số như một chuỗi (bạn phải nếu bạn khởi tạo BigDecimal mà không có đối số 'precision'), tại sao không chỉ làm' n [/ \ d + $ /]. Size'? –

0

Câu trả lời của Olexandr không hoạt động đối với số nguyên. Có thể thử như sau:

def decimals(num) 
    if num 
    arr = num.to_s.split('.') 
    case arr.size 
     when 1 
     0 
     when 2 
     arr.last.size 
     else 
     nil 
    end 
    else 
    nil 
    end 
end 
Các vấn đề liên quan