बिट डेटा को Arrays pack
के माध्यम से उजागर किया जा सकता है क्योंकि फ्लोट आंतरिक रूप से कार्य प्रदान नहीं करता है।
str = [12.125].pack('D').bytes.reverse.map{|n| "%08b" %n }.join
=> "0100000000101000010000000000000000000000000000000000000000000000"
[ str[0], str[1..11], str[12..63] ]
=> ["0", "10000000010", "1000010000000000000000000000000000000000000000000000"]
यह स्ट्रिंग प्रस्तुति से इसे खींचने के लिए 'घरों के चारों ओर' थोड़ा सा है। मुझे यकीन है कि वहाँ मूल bytes
से डेटा खींचने के लिए एक अधिक कुशल तरीका है हूँ ...
संपादित बिट स्तर हेरफेर मेरी रुचि बदलाव तो मैं एक प्रहार के आसपास था। रुबी में परिचालनों का उपयोग करने के लिए आपको एक इंटीजर होना चाहिए ताकि फ्लोट को 64 बिट int में परिवर्तित करने के लिए कुछ और unpack
आईएनजी की आवश्यकता हो। बड़ा एंडियन/यानी 754 दस्तावेजी प्रतिनिधित्व काफी मामूली है। थोड़ा एंडियन प्रतिनिधित्व मैं इस बारे में इतना निश्चित नहीं हूँ। यह थोड़ा अजीब है, क्योंकि आप 11 बिट एक्सपोनेंट और 52 बिट मंटिसा के साथ पूर्ण बाइट सीमाओं पर नहीं हैं। बिट्स को खींचने और उन्हें छोटे एंडियन जैसा दिखने के लिए उन्हें स्वैप करना मुश्किल हो जाता है, और यह सुनिश्चित नहीं है कि यह सही है क्योंकि मैंने लेआउट का कोई संदर्भ नहीं देखा है। तो 64 बिट मान थोड़ा एंडियन है, मुझे यकीन नहीं है कि यह 64 बिट मूल्य के घटकों पर कैसे लागू होता है जब तक आप उन्हें कहीं और स्टोर नहीं करते हैं, जैसे कि मंटिसा के लिए 16 बिट इंट।
छोटे से छोटे से 11 बिट मान के लिए एक उदाहरण के रूप में, मैं जिस तरह की चीज कर रहा था वह सबसे महत्वपूर्ण बाइट बाएं 3 को सामने, या कम से कम महत्वपूर्ण 3 बिट्स को स्थानांतरित करना था।
v = 0x4F2
((v & 0xFF) << 3) | (v >> 8))
यह वैसे भी है, उम्मीद है कि इसका कुछ उपयोग है।
class Float
Float::LITTLE_ENDIAN = [1.0].pack("E") == [1.0].pack("D")
# Returns a sign, exponent and mantissa as integers
def ieee745_binary64
# Build a big end int representation so we can use bit operations
tb = [self].pack('D').unpack('Q>').first
# Check what we are
if Float::LITTLE_ENDIAN
ieee745_binary64_little_endian tb
else
ieee745_binary64_big_endian tb
end
end
# Force a little end calc
def ieee745_binary64_little
ieee745_binary64_little_endian [self].pack('E').unpack('Q>').first
end
# Force a big end calc
def ieee745_binary64_big
ieee745_binary64_big_endian [self].pack('G').unpack('Q>').first
end
# Little
def ieee745_binary64_little_endian big_end_int
#puts "big #{big_end_int.to_s(2)}"
sign = (big_end_int & 0x80 ) >> 7
exp_a = (big_end_int & 0x7F ) << 1 # get the last 7 bits, make it more significant
exp_b = (big_end_int & 0x8000) >> 15 # get the 9th bit, to fill the sign gap
exp_c = (big_end_int & 0x7000) >> 4 # get the 10-12th bit to stick on the front
exponent = exp_a | exp_b | exp_c
mant_a = (big_end_int & 0xFFFFFFFFFFFF0000) >> 12 # F000 was taken above
mant_b = (big_end_int & 0x0000000000000F00) >> 8 # F00 was left over
mantissa = mant_a | mant_b
[ sign, exponent, mantissa ]
end
# Big
def ieee745_binary64_big_endian big_end_int
sign = (big_end_int & 0x8000000000000000) >> 63
exponent = (big_end_int & 0x7FF0000000000000) >> 52
mantissa = (big_end_int & 0x000FFFFFFFFFFFFF) >> 0
[ sign, exponent, mantissa ]
end
end
और परीक्षण ...
def printer val, vals
printf "%-15s sign|%01b|\n", val, vals[0]
printf " hex e|%3x| m|%013x|\n", vals[1], vals[2]
printf " bin e|%011b| m|%052b|\n\n", vals[1], vals[2]
end
floats = [ 12.125, -12.125, 1.0/3, -1.0/3, 1.0, -1.0, 1.131313131313, -1.131313131313 ]
floats.each do |v|
printer v, v.ieee745_binary64
printer v, v.ieee745_binary64_big
end
मेरे मस्तिष्क टीआईएल बड़ा endian है! आप ध्यान देंगे कि इन चीजों के साथ काम किया जा रहा है दोनों बड़े एंडियन हैं। मैं दूसरी तरफ स्थानांतरित करने में असफल रहा।
जॉन, [आईईईई 754] (http://en.wikipedia.org/wiki/IEEE_floating_point) के उल्लेख के लिए धन्यवाद, फ्लोट का प्रतिनिधित्व। मुझे इस बारे में पता नहीं था।अगर किसी पाठकों को अनुस्मारक की आवश्यकता होती है, तो एक उदाहरण गणना दी जाती है [यहां] (http://class.ece.iastate.edu/arun/cpre381/ieee754/ie4.html)। –