2011-09-18 21 views
5

Tôi muốn chuyển đổi từ xu sang đô la một cách chính xác trong Ruby. Tôi sẽ không bao giờ phải làm việc với phân số cent.Chuyển đổi xu thành chuỗi đô la trong Ruby mà không sử dụng BigDecimal

Có thể thực hiện điều này một cách chính xác (không có lỗi dấu phẩy động) mà không phải sử dụng BigDecimal?

Ví dụ: cent sang đô la

"99" => "0.99" 
"324" => "3.24" 

Sau đây dường như làm việc, nhưng là nó có đúng không?

(cents.to_i/100.0).to_s 
+0

Phụ thuộc vào độ chính xác bạn cần. Nếu bạn đồng ý với độ chính xác trung bình, hãy dùng gem tiền. – Philip

Trả lời

3

Cá nhân tôi sẽ không cố gắng phát minh lại bánh xe cụ thể này và đi theo số money gem. Từ các tài liệu (nhấn mạnh thêm):

Tính năng

Cung cấp một lớp học tiền mà gói gọn tất cả các thông tin về một số tiền nhất định, chẳng hạn như giá trị của nó và đồng nhân dân tệ.

Cung cấp tiền :: Lớp tiền tệ bao gồm tất cả thông tin về đơn vị tiền tệ .

Trình bày các giá trị tiền tệ dưới dạng số nguyên, tính bằng xu. Điều này tránh lỗi làm tròn dấu phẩy động.

Đại diện tiền tệ là Tiền :: Các trường hợp tiền tệ cung cấp mức độ linh hoạt cao.

Cung cấp API để trao đổi tiền từ loại tiền tệ này sang đơn vị tiền tệ khác.

Có khả năng phân tích cú pháp một chuỗi tiền và tiền tệ thành đối tượng tiền/tiền tệ tương ứng.

+0

Trên thực tế tiền đá quý [sử dụng BigDecimal] (https://github.com/RubyMoney/money/blob/master/lib/money/money/arithmetic.rb) để thực hiện các bộ phận. – Philip

+0

Đủ công bằng. Như tôi đã nói, OP không nói với chúng tôi quá nhiều về những gì anh định làm, nhưng tôi cho một người không muốn giải quyết mọi rắc rối về tiền bạc khi ai đó đã làm điều đó. –

8

Micheal Kohl already answered: Hãy xem đá quý tiền.

Ví dụ:

require 'money' 
Money.use_i18n = false #https://stackoverflow.com/q/31133229/676874 
puts Money.new(99, 'USD') 
puts Money.new(324, 'USD') 

Sau đây dường như làm việc, nhưng là nó có đúng không?

(cents.to_i/100.0).to_s 

Trên cái nhìn đầu tiên, nó là ok, nhưng:

cents = '10' 
p (cents.to_i/100.0).to_s # -> '0.1' 

Bạn không có 2 chữ số.

Alternative:

p '%.2f' % (cents.to_i/100.0) # -> '0.10' 
+7

Cảm ơn bạn đã cung cấp giải pháp thay vì chỉ nói "sử dụng đá quý này". –

1

Bạn có thể xem xét sử dụng rationals là tốt.Tuy nhiên, tôi không chắc chắn làm họ nhận được chuyển đổi sang nổi khi sprintf-ed:

"%.2f" % Rational("324".to_i,100) 
#=> "3.24" 
"%.2f" % Rational("99".to_i,100) 
#=> "0.99" 
"%.2f" % Rational("80".to_i,100) 
#=> "0.80" 
"%.2f" % Rational("12380".to_i,100) 
#=> "123.80" 
4

Nếu họ đốt đã bạn có thể sử dụng chuỗi thao tác và bỏ qua những vấn đề số hoàn toàn:

# There are, of course, all sorts of ways to do this. 
def add_decimal(s) 
    pfx = [ '0.00', '0.0', '0.' ] 
    if(pfx[s.length]) 
     s = pfx[s.length] + s 
    else 
     s = s.dup 
     s[-2, 0] = '.' 
    end 
    s 
end 

add_decimal('')  # "0.00" 
add_decimal('1')  # "0.01" 
add_decimal('12') # "0.12" 
add_decimal('123') # "1.23" 
add_decimal('1234') # "12.34" 
add_decimal('12345') # "123.45" 

Không vấn đề chính xác, không có điểm nổi, không có bignums, không có Rational, không có gì phức tạp, không có gì thông minh. Một số sửa đổi đơn giản sẽ là cần thiết để đối phó với các giá trị tiêu cực nhưng điều đó sẽ đơn giản như những gì đã có.

Các vấn đề liên quan