array of bytes to num - ruby

I have for example
tab = [0x51, 0x3c, 0xb8, 0x15]
then I want to convert this table to integer
0x15b83c51 = 363323840
any ideas?

Possible solution:
> tab.reverse.inject("") {|s,a| s<<a.to_s(16) }.to_i(16)
=> 364395601

I'm not very familiar with the bit/hex functions in ruby, so sorry if it's not more specific or precise, but... have you tried to:
bitnum = 0
while hexnum = tab.pop do
# 1. convert hexnum to binary format
# 2. bit-shift bitnum accordingly
end

tab.reverse.inject {|s,a| (s<<8) + a}
# => 364395601

(I have no idea how you get 363323840 from 0x15b83c51. Like other people already answered, 0x15b83c51 is 364395601)
Here is yet another solution, which also works if you have more than one integer to decode in your table.
# Convert to binary string
binaryString = [0x51, 0x3c, 0xb8, 0x15].map(&:chr).join
# Convert the binary string to an unsigned integer array
# and take its first element
number = binaryString.unpack("I").first

Related

How to convert an octet string to a number?

I am trying to convert an octet string into an Integer in Ruby.
For now I have this solution:
def octet_string_to_i(str)
str.bytes.map { |v| format('%08b', v) }.join.to_i(2)
end
It feels like total overkill. I found other questions about converting it to a string but none about an Integer. Is there any way to achieve this without first going through a string as in my solution?
Example values and results:
foobar 112628796121458
barbaz 108170670399866
123456 54091677185334
Using the following code:
str.bytes.reverse_each.with_index.sum {|elem, idx| elem << (idx * 8) }
Basically, we reduce the bytes by adding them to a sum, shifting each byte to its proper position using their index. This avoids having to first convert to a string and back, and achieves the same result.
Credit goes to Sergio Tulentsev for the code.

How to convert 64 bit binary string to a double float in ruby?

I am wondering how to convert a 64 bit binary string to a double float in ruby. The string that I have is as follows:
binaryString = "0011111111110000000000000000000000000000000000000000000000000000"
Using an online converter (http://www.binaryconvert.com/convert_double.html?) I know that the value should be 1.0. However, I'm attempting to use the ruby unpack to convert to double, and I'm not getting the correct result.
double_value = binaryString.unpack("G")
Gives me double_value = 1.3983819593719592e-76
I've tried other directives like "F" and "D", but none yield correct results.
Any ideas what I am doing wrong? Thank you for the help!
unpack expects binary data, so you have to pack your bit string first using B:
b = '0011111111110000000000000000000000000000000000000000000000000000'
[b].pack('B*').unpack1('G')
#=> 1.0

extract data from variable in ruby on rails

I have a variable in ruby on rails which contains this value 8,375 TND
_result = _orig_account.formatted_balance(_currency)
I want if it is possible to eliminate TND and then multiply the rest by 1000 in order to have as a result 8375
can sameone help me to solve this problem
I try with this code :
I try with : _tes = _orig_account.formatted_balance().tr(',', '.').to_f
_te = _tes * 1000
and I have as a result : 8375.0
but as I said I want juste 8375
UPDATE: Just use this '8,375 TND'.tr(',', '').to_i
It's a simple manipulation:
'8,375 TND'.tr(',', '.').to_f
=> 8.375
Multiply that by 1000.

packet creation in ruby

I'm trying to create a packet to send over serial using ruby-serialport. This seems like it should be simple, and it works when I just write a string:
packet = "\xFF\x03\x10\x01\x01\xFE"
sp.write(packet)
=>hardware does what it's supposed to, opens the door represented by the 4th hex value
but I obviously need to do it programmatically, and I can't figure out the right way. Here are just a few of the things I've tried:
door = 1
packet = "\xFF\x03\x10" + door.to_s(16) + "\x01\xFE"
sp.write(packet)
=> can't convert fixnum into string
and
door = 1
packet = "\xFF\x03\x10" + door.to_a.pack('H*') + "\x01\xFE"
sp.write(packet)
=> to_a will be obsolete
can't convert fixnum into string
and
door = 1
sp.write("\xFF\x03\x10")
sp.write(door)
sp.write("\x01\xFE")
=>no response from hardware
Can anyone help me out on how to properly convert a number into the right hex notation for serialport and joining to the other hex strings? Thanks in advance!
You're really going to get into trouble if you insist on using strings to represent otherwise binary data. What you really need is pack:
packet = [ 0xFF, 0x30, 0x10, door, 0x01, 0xFE ].pack('C*')
This makes it very easy to construct and deconstruct arbitrary binary data. The method supports not just unsigned characters but a variety of other types that are commonly used.
You may even want to construct your own method to read and write this:
def write_packet(*bytes)
sp.write(bytes.flatten.pack('C*'))
end
Try this:
door = 1
packet = "\xFF\x03\x10" + door.chr + "\x01\xFE"

Calculating the size of an Array pack struct format in Ruby

In the case of e.g. ddddd, d is the native format for the system, so I can't know exactly how big it will be.
In python I can do:
import struct
print struct.calcsize('ddddd')
Which will return 40.
How do I get this in Ruby?
I haven't found a built-in way to do this, but I've had success with this small function when I know I'm dealing with only numeric formats:
def calculate_size(format)
# Only for numeric formats, String formats will raise a TypeError
elements = 0
format.each_char do |c|
if c =~ /\d/
elements += c.to_i - 1
else
elements += 1
end
end
([ 0 ] * elements).pack(format).length
end
This constructs an array of the proper number of zeros, calls pack() with your format, and returns the length (in bytes). Zeros work in this case because they're convertible to each of the numeric formats (integer, double, float, etc).
I don't know of a shortcut but you can just pack one and ask how long it is:
length_of_five_packed_doubles = 5 * [1.0].pack('d').length
By the way, a ruby array combined with the pack method appears to be functionally equivalent to python's struct module. Ruby pretty much copied perl's pack and put them as methods on the Array class.

Resources