ฉันจำเป็นต้องสามารถกำหนดจำนวนเต็มสูงสุดของระบบใน Ruby ใครรู้วิธีหรือถ้าเป็นไปได้?
ฉันจำเป็นต้องสามารถกำหนดจำนวนเต็มสูงสุดของระบบใน Ruby ใครรู้วิธีหรือถ้าเป็นไปได้?
คำตอบ:
Ruby จะแปลงจำนวนเต็มเป็นคลาสจำนวนเต็มขนาดใหญ่โดยอัตโนมัติเมื่อมันล้นดังนั้นจึงไม่มีข้อ จำกัด (ในทางปฏิบัติ) ว่าจะใหญ่แค่ไหน
หากคุณกำลังมองหาขนาดของเครื่องเช่น 64- หรือ 32 บิตฉันพบเคล็ดลับนี้ที่ 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
หากคุณกำลังมองหาขนาดของอ็อบเจ็กต์ Fixnum (จำนวนเต็มเล็กพอที่จะจัดเก็บในเครื่องคำเดียว) คุณสามารถโทร0.size
เพื่อรับจำนวนไบต์ได้ ฉันเดาว่ามันควรจะเป็น 4 ในรุ่น 32 บิต แต่ฉันไม่สามารถทดสอบได้ในตอนนี้ นอกจากนี้ Fixnum ที่ใหญ่ที่สุดยังเห็นได้ชัด2**30 - 1
(หรือ2**62 - 1
) เนื่องจากมีการใช้หนึ่งบิตเพื่อทำเครื่องหมายเป็นจำนวนเต็มแทนที่จะเป็นการอ้างอิงวัตถุ
FIXNUM_MAX = (2**(0.size * 8 -2) -1)
FIXNUM_MIN = -(2**(0.size * 8 -2))
Fixnum
จะเป็น 64 บิตเสมอ (ไม่ใช่ 63 หรือ 31 บิตเหมือนใน YARV) โดยไม่คำนึงถึงขนาดคำของเครื่องและไม่มีบิตแท็ก
อ่านคู่มือที่เป็นมิตร? ใครอยากทำแบบนั้น?
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"
puts (Fixnum::MAX + 1).class
นี้ไม่ได้ผลBignum
อย่างที่ควรจะเป็น ถ้าคุณเปลี่ยน8
ไป16
ก็จะ
ไม่มีค่าสูงสุดตั้งแต่ Ruby 2.4 เนื่องจาก Bignum และ Fixnum รวมกันเป็น Integer ดูคุณลักษณะ # 12005
> (2 << 1000).is_a? Fixnum
(irb):322: warning: constant ::Fixnum is deprecated
=> true
> 1.is_a? Bignum
(irb):314: warning: constant ::Bignum is deprecated
=> true
> (2 << 1000).class
=> Integer
จะไม่มีสิ่งใดล้นสิ่งที่จะเกิดขึ้นคือความทรงจำไม่เพียงพอ
ดังที่ @ Jörg W Mittag ชี้ให้เห็น: ใน jruby ขนาดฟิกซ์ num จะยาว 8 ไบต์เสมอ ข้อมูลโค้ดนี้แสดงความจริง:
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