2009-07-03 27 views
24

Trong ruby, tôi muốn chuyển đổi một phao sang một int nếu đó là một số nguyên. Ví dụ:Vòng tròn Ruby to_int nếu toàn bộ số

a = 1.0 
b = 2.5 

a.to_int_if_whole # => 1 
b.to_int_if_whole # => 2.5 

Về cơ bản, tôi đang cố tránh hiển thị ".0" trên bất kỳ số nào không có số thập phân. Tôi đang tìm cách thanh lịch (hoặc được xây dựng) để làm

def to_int_if_whole(float) 
    (float % 1 == 0) ? float.to_i : float 
end 

Trả lời

5

Đây là giải pháp mà kết thúc làm việc theo cách mà tôi muốn nó:

class Float 
    alias_method(:original_to_s, :to_s) unless method_defined?(:original_to_s) 

    def is_whole? 
    self % 1 == 0 
    end 

    def to_s 
    self.is_whole? ? self.to_i.to_s : self.original_to_s 
    end 
end 

Bằng cách này tôi có thể cập nhật các logic is_whole? (Tôi có vẻ như tadman được những phức tạp nhất), nếu cần thiết, và nó đảm bảo bất cứ nơi nào một Float đầu ra đến một chuỗi (ví dụ, trong một hình thức) nó xuất hiện theo cách tôi muốn nó (tức là, không có số không ở cuối).

Cảm ơn mọi người vì những ý tưởng của bạn - chúng thực sự hữu ích.

3

Tôi không biết nhiều về Ruby.

Nhưng đây là sự cố hiển thị . Tôi sẽ vô cùng ngạc nhiên nếu các thư viện bạn đang sử dụng không có cách nào để định dạng một số khi bạn chuyển đổi nó thành một chuỗi.

Có thể không có tùy chọn định dạng bắt tất cả thực hiện chính xác những gì bạn muốn nhưng bạn có thể thiết lập phương thức trả về true nếu phao là đại diện nổi của một số nguyên và ngược lại. Bên trong một thói quen định dạng mà bạn tạo ra (vì vậy bạn chỉ phải làm điều này ở một nơi) chỉ cần thay đổi định dạng dựa trên nếu điều này là đúng hay sai.

This thảo luận cách kiểm soát số chữ số xuất hiện sau chữ số thập phân khi hiển thị số.

Xem ra sự phức tạp của biểu diễn điểm nổi. Toán học có thể nói câu trả lời là 3 nhưng bạn có thể nhận được 3.000000000000000000001. Tôi muốn đề nghị sử dụng một đồng bằng để xem nếu số gần như là một số nguyên.

+0

Điều này đúng, nhưng tôi muốn nó hiển thị theo cách này * ở khắp mọi nơi * một đầu ra dạng float dưới dạng một chuỗi. Về cơ bản tôi muốn ghi đè lên phương thức Float.to_s, hoặc treo logic này vào cuối nó. –

2

Mặc dù tôi muốn có xu hướng đồng ý với bài viết ở trên, nếu bạn phải làm điều này:

(float == float.floor) ? float.to_i : float 
0

Tôi không biết nhiều về Ruby một trong hai.

Nhưng trong C++, tôi muốn làm điều này:

bool IsWholeNumber(float f) 
{ 
    const float delta = 0.0001; 
    int i = (int) f; 
    return (f - (float)i) < delta; 
} 

Và sau đó tôi muốn định dạng chính xác đầu ra dựa trên đó.

48

Một cách đơn giản để nó sẽ là:

class Float 
    def prettify 
    to_i == self ? to_i : self 
    end 
end 

Đó là bởi vì:

irb> 1.0 == 1 
=> true 
irb> 1 == 1.0 
=> true 

Sau đó, bạn có thể làm:

irb> 1.0.prettify 
=> 1 

irb> 1.5.prettify 
=> 1.5 
1

Dưới đây là thực hiện khủng khiếp hacktastic tôi cung cấp cho các mục đích giáo dục :

class Float 
    def to_int_if_whole(precision = 2) 
    ("%.#{precision}f" % self).split(/\./).last == '0' * precision and self.to_i or self 
    end 
end 

puts 1.0.to_int_if_whole # => 1 
puts 2.5.to_int_if_whole # => 2.5 
puts 1.9999999999999999999923.to_int_if_whole # => 2 

Lý do sử dụng cuộc gọi kiểu sprintf là nó xử lý các điểm xấp xỉ dấu phẩy động đáng tin cậy hơn nhiều so với phương thức Float # tròn có xu hướng.

41

Một sprintf lót ...

sprintf("%g", 5.0) 
=> "5" 

sprintf("%g", 5.5) 
=> "5.5" 
+0

Bạn sẽ làm điều gì đó như '" # {% g, percent}% off "'? Có thể là một lớp lót không? – Dennis

+0

cảm ơn rất nhiều, chỉ là những gì tôi đang tìm kiếm. – Toontje

+0

Không chính xác, khiến nó không chỉ giảm '.0', mà còn tất cả mọi thứ nếu số mũ nhỏ hơn -4, và làm tròn nó, ví dụ:' "% g"% 1.123456789 # => "1.12346" ' –

2

Nếu bạn đang sử dụng đường ray, bạn có thể sử dụng helper number_to_rounded với tùy chọn strip_insignificant_zeros, ví dụ:

ActiveSupport::NumberHelper.number_to_rounded(42.0, strip_insignificant_zeros: true) 

hay như thế này:

42.0.to_s(:rounded, strip_insignificant_zeros: true) 
Các vấn đề liên quan