Reading a binary 16-bit signed (big-endian) integer in Ruby - ruby

I tried to read from a file where numbers are stored as 16-bit signed integers in big-endian format.
I used unpack to read in the number, but there is no parameter for a 16-bit signed integer in big-endian format, only for an unsigned integer. Here is what I have so far:
number = f.read(2).unpack('s')[0]
Is there a way to interpret the number above as a signed integer or another way to achieve what I want?

I don't know if it's possible to use String#unpack for that, but to convert a 16bit-unsigned to signed, you can use the classical method:
>> value = 65534
>> (value & ~(1 << 15)) - (value & (1 << 15))
=> -2

Use BinData and there's no need for bit twiddling.
BinData::Int16be.read(io)

Found a solution that works by reading two 8bit unsigned integers and convert them to a 16bit big-endian integer
bytes = f.read(2).unpack('CC')
elevation = bytes[0] << 8 | bytes[1]

Apparently since Ruby 1.9.3 you can actually suffix the s with endiannes like so:
io.read(2).unpack('s>')

Related

How to convert a signed integer to an unsigned integer in Ruby?

I have a number that I received from a C program that came to me as a negative number:
-1771632774
It's supposed to be this number:
2523334522
I realized that this must be due to some conversion from an signed integer to an unsigned integer. Now that I have this negative number in Ruby, how can I convert it back to the unsigned version?
Put the negative integer in an array. Call pack with an argument of 'L' which represents "32-bit unsigned, native endian (uint32_t)". Call unpack with the same argument. Finally, get the number out of the array.
[-1771632774].pack('L').unpack('L').first
#=> 2523334522
http://ruby-doc.org/core-2.4.0/Array.html#method-i-pack

How to represent 11111111 as a byte in java

When I say that 0b11111111 is a byte in java, it says " cannot convert int to byte," which is because, as i understand it, 11111111=256, and bytes in java are signed, and go from -128 to 127. But, if a byte is just 8 bits of data, isn't 11111111 8 bits? I know 11111111 could be an integer, but in my situation it must be represented as a byte because it must be sent to a file in byte form. So how do I send a byte with the bits 11111111 to a file(by the way, this is my question)? When I try printing the binary value of -1, i get 11111111111111111111111111111111, why is that? I don't really understand how signed bytes work.
You need to cast the value to a byte:
byte b = (byte) 0b11111111;
The reason you need the cast is that 0b11111111 is an int literal (with a decimal value of 255) and it's outside the range of valid byte values (-128 to +127).
Java allows hex literals, but not binary. You can declare a byte with the binary value of 11111111 using this:
byte myByte = (byte) 0xFF;
You can use hex literals to store binary data in ints and longs as well.
Edit: you actually can have binary literals in Java 7 and up, my bad.

Convert HEX 32 bit from GPS plot on Ruby

I am working with the following HEX values representing different values from a GPS/GPRS plot. All are given as 32 bit integer.
For example:
296767 is the decimal value (unsigned) reported for hex number: 3F870400
Another one:
34.96987500 is the decimal float value (signed) given on radian resolution 10^(-8) reported for hex humber: DA4DA303.
Which is the process for transforming the hex numbers onto their corresponding values on Ruby?
I've already tried unpack/pack with directives: L, H & h. Also tried adding two's complement and converting them to binary and then decimal with no success.
If you are expecting an Integer value:
input = '3F870400'
output = input.scan(/../).reverse.join.to_i( 16 )
# 296767
If you are expecting degrees:
input = 'DA4DA303'
temp = input.scan(/../).reverse.join.to_i( 16 )
temp = ( temp & 0x80000000 > 1 ? temp - 0x100000000 : temp ) # Handles negatives
output = temp * 180 / (Math::PI * 10 ** 8)
# 34.9698751282937
Explanation:
The hexadecimal string is representing bytes of an Integer stored least-significant-byte first (or little-endian). To store it as raw bytes you might use [296767].pack('V') - and if you had the raw bytes in the first place you would simply reverse that binary_string.unpack('V'). However, you have a hex representation instead. There are a few different approaches you might take (including putting the hex back into bytes and unpacking it), but in the above I have chosen to manipulate the hex string into the most-significant-byte first form and use Ruby's String#to_i

TCL: convert negative integer to hexadecimal?

I want to convert signed integer to 32-bit hexadecimal.
The following works fine for positive integer:
format %.8x $the_decimal_value
But for negative integer, I got 64-bit hexadecimal.
For example, 99 is converted to 00000063, but -81 is converted to ffffffffffffffaf.
Anyone know how to get 32-bit hexadecimal from a negative integer?
% set num -81
% format 0x%.8x [expr {$num & 0xFFFFFFFF}]
0xffffffaf
The only hint in the docs I can find is this.

converting a wire value to an integer in verilog

I want to convert the data in a wire to an integer. For example:
wire [2:0] w = 3'b101;
I want a method that converts this to '5' and stores it in an integer. How can I do that in a better way than this:
j=1;
for(i=0; i<=2; i=i+1)
begin
a=a+(w[i]*j);
j=j*2;
end
Also, how do I convert it back to binary once I have the value in an integer? This seems a clumsy way. Thank you.
Easy! Conversion is automatic in verilog if you assign to an integer. In verilog, all the data types are just collection on bits.
integer my_int;
always #( w )
my_int = w;
As Marty said : conversion between bit vectors and integers is automatic.
But there are a number of pitfalls. They are obvious if you keep in mind that an integer is a 32 bit signed value.
Don't try to assign e.g. a 40 bit value to an integer.
Default bit vector are unsigned so a 32 bit vector may become negative when it is an integer.
The opposite is also true: a negative integer e.g. -3 will become an 8 vector with value 8'b11111101
I don't know why you want to convert to an integer and back. I just want to point out that arithmetic operations are fully supported on signed and unsigned bit vectors. In fact they are more powerful as there is no 32-bit limit:
reg [127:0] huge_counter;
...
always #(posedge clk)
huge_counter <= huge_counter + 128'h1;
Also using a vector as index is supported:
wire [11:0] address;
reg [ 7:0] memory [0:4095];
...
assign read_data = memory[address];

Resources