2010-01-13 37 views
8

Trong khi viết một bài kiểm tra với một giá trị được đại diện như một BigDecimal, tôi chạy vào một cái gì đó kỳ lạ và quyết định đào sâu vào nó. Tóm lại, '0.00009' khi được làm tròn đến hai chữ số thập phân được trả về là 0,01 thay vì 0,00. Có thật không. Dưới đây là tôi kịch bản/console chụp:Vòng BigDecimal của Ruby: Đây có phải là lỗi không?

>> bp = BigDecimal('0.09') 
=> #<BigDecimal:210fe08,'0.9E-1',4(8)> 
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f 
=> 0.09 
>> bp = BigDecimal('0.009') 
=> #<BigDecimal:210bcf4,'0.9E-2',4(8)> 
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f 
=> 0.01 
>> bp = BigDecimal('0.0009') 
=> #<BigDecimal:2107a8c,'0.9E-3',4(12)> 
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f 
=> 0.0 
>> bp = BigDecimal('0.00009') 
=> #<BigDecimal:2103428,'0.9E-4',4(12)> 
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f 
=> 0.01 
>> bp = BigDecimal('0.000009') 
=> #<BigDecimal:20ff0f8,'0.9E-5',4(12)> 
>> bp.round(2,BigDecimal::ROUND_HALF_DOWN).to_f 
=> 0.0 

Oh, và tôi nhận được kết quả tương tự nếu tôi sử dụng chế độ mặc định, như vậy:

>> bd = BigDecimal('0.00009') 
=> #<BigDecimal:2152ed8,'0.9E-4',4(12)> 
>> bd.round(2).to_f 
=> 0.01 

Dưới đây là phiên bản của tôi:

ruby 1.8.6 (2008-03-03 patchlevel 114) [i686-darwin9.2.2] 
Rails 2.3.4 

Có ai nhìn thấy bất cứ điều gì như thế này không?

+0

Tôi không thể tái tạo nó trong môi trường 1.8.7 của tôi (ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux]) – bryantsai

Trả lời

6

Không, chưa bao giờ thấy điều này trước đây, và nó chắc chắn trông giống như một lỗi. 0.00009 được làm tròn đến hai chữ số thập phân chắc chắn là 0.00.

ROUND_HALF_DOWN không được thay đổi hành vi vì bạn không xử lý các giá trị điểm giữa.

This link có thêm chi tiết.

Dường như đây là lỗi trong 1,8 cấp đã được sửa trong phiên bản 1.9. Đó là một chút kỳ lạ ở chỗ nó chỉ có vẻ ảnh hưởng đến các con số với một số chẵn thậm chí trước chữ số đầu tiên khác 0 và chỉ khi chữ số đó là 5 hoặc lớn hơn.

Có vẻ như là chính xác sự cố của bạn dựa trên dữ liệu được cung cấp.

+0

Đúng, điều này dường như chính xác là vấn đề của tôi! Cảm ơn cho sleuthing! –

0

Tôi nghĩ, đây cũng là một lỗi, nhưng điều tôi tự hỏi là .to_f để hiển thị kết quả. Với BigDecimal bạn nên sử dụng .to_s ('F') thay vì kể từ khi tôi đoán bạn có một lý do để sử dụng BigDecimal thay vì Floats.

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