Tôi cần có khả năng xác định số nguyên tối đa của hệ thống trong Ruby. Ai biết làm thế nào, hoặc nếu nó có thể?Số nguyên tối đa Ruby
Trả lời
Ruby tự động chuyển đổi số nguyên thành một lớp số nguyên lớn khi chúng tràn, do đó, (thực tế) không có giới hạn về mức độ lớn của chúng.
Nếu bạn đang tìm kiếm kích thước của máy, tức là 64 hoặc 32-bit, tôi thấy this trick at ruby-forum.com:
machine_bytes = ['foo'].pack('p').size
machine_bits = machine_bytes * 8
machine_max_signed = 2**(machine_bits-1) - 1
machine_max_unsigned = 2**machine_bits - 1
Nếu bạn đang tìm kiếm kích thước của các đối tượng Fixnum (số nguyên đủ để nhỏ lưu trữ trong một từ máy), bạn có thể gọi 0.size
để nhận số byte. Tôi đoán nó sẽ là 4 trên 32-bit, nhưng tôi không thể kiểm tra ngay bây giờ. Ngoài ra, Fixnum lớn nhất rõ ràng là 2**30 - 1
(hoặc 2**62 - 1
), bởi vì một bit được sử dụng để đánh dấu nó như là một số nguyên thay vì một tham chiếu đối tượng.
Trong ruby Fixnums được tự động chuyển đổi thành Bignums.
Để tìm Fixnum cao nhất có thể bạn có thể làm một cái gì đó như thế này:
class Fixnum
N_BYTES = [42].pack('i').size
N_BITS = N_BYTES * 8
MAX = 2 ** (N_BITS - 2) - 1
MIN = -MAX - 1
end
p(Fixnum::MAX)
shamelessly tách từ một ruby-talk discussion. Nhìn ở đó để biết thêm chi tiết.
Nếu bạn đặt 'đặt (Fixnum :: MAX + 1) .class' này không trả về' Bignum' giống như nó có vẻ như cần. Nếu bạn thay đổi '8' thành' 16' nó sẽ. –
tính năng này hiện không khả dụng – allenhwkim
Đọc hướng dẫn sử dụng thân thiện? Ai muốn làm vậy?
start = Time.now
largest_known_fixnum = 1
smallest_known_bignum = nil
until smallest_known_bignum == largest_known_fixnum + 1
if smallest_known_bignum.nil?
next_number_to_try = largest_known_fixnum * 1000
else
next_number_to_try = (smallest_known_bignum + largest_known_fixnum)/2 # Geometric mean would be more efficient, but more risky
end
if next_number_to_try <= largest_known_fixnum ||
smallest_known_bignum && next_number_to_try >= smallest_known_bignum
raise "Can't happen case"
end
case next_number_to_try
when Bignum then smallest_known_bignum = next_number_to_try
when Fixnum then largest_known_fixnum = next_number_to_try
else raise "Can't happen case"
end
end
finish = Time.now
puts "The largest fixnum is #{largest_known_fixnum}"
puts "The smallest bignum is #{smallest_known_bignum}"
puts "Calculation took #{finish - start} seconds"
Điều này có vẻ là câu trả lời duy nhất trả về số khi chuyển từ Fixnum sang Bignum, với tôi, có nghĩa là Fixnum lớn nhất trong Ruby. –
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
FIXNUM_MIN = -(2**(0.size * 8 -2))
Tại sao bạn trừ 2 bit thay vì 1 cho dấu? Tôi đã thử nghiệm này và nó có vẻ là chính xác, nhưng tại sao Ruby sử dụng 2 bit cho các dấu hiệu? – Matthias
@Matthias Một bit phụ được sử dụng để đánh dấu giá trị dưới dạng số nguyên (ngược với một con trỏ đến một đối tượng). –
Thú vị, cảm ơn! – Matthias
như @ Jörg W Mittag chỉ ra: trong JRuby, sửa kích thước num luôn có chiều dài 8 byte. Đoạn mã này cho thấy sự thật:
fmax = ->{
if RUBY_PLATFORM == 'java'
2**63 - 1
else
2**(0.size * 8 - 2) - 1
end
}.call
p fmax.class # Fixnum
fmax = fmax + 1
p fmax.class #Bignum
Khá chắc chắn bạn muốn 2 ** (machine_size * 8) -1; 2 ** 4-1 = 15 không phải là một thứ rất lớn. – Cebjyre
Rất tiếc, tôi đoán tôi đã bắt đầu suy nghĩ quá nhiều về byte thay vì bit. –
CẢNH BÁO: Mã này vô dụng. Đọc chỉnh sửa, bỏ qua mã. Nó không tìm thấy bất cứ thứ gì tối đa cho Ruby. Nó tìm thấy nó cho mã mà không sử dụng con trỏ được gắn thẻ. –