How do I properly convert a 64-bit binary string / Convert directly from bin or hex to uint64
47 views (last 30 days)
Show older comments
I have a matlab function that reads in serial data and breaks it apart into component signals.
Each serial data packet is 64 bits.
Update: The data originates from a data capture which stores it as hex string of up to 16 characters.
Each packet is broken up into an arbitrary number of variables with an arbitrary number of bits. Often, they are bytes, but sometimes they are "odd" numbers of bits. Because of this, I have to analyze these packets bit-wise, first converting from Hex to Bin(update), then extract the necessary bits, then re-order them, in order to get the correct data. That is, when I convert the raw data into binary strings, the Matlab indicies 1-64 correspond to bits 63->0 in the serial data.
This is usually OK in most cases, but one particular variable actually uses ALL 64 bits.
The problem that arises from this, is if my 64-bit integer is greater than 2^53 (flintmax), then it will not get converted correctly. MATLAB gives me a warning about this. This is because both hex2dec and bin2dec convert to type double. There's no direct conversion from bin->hex or from bin->int that I'm aware of.
All of the variables are integer based (update: that is all of the serial data represented in Hex, ultimately represent integer numbers). How do I properly convert the 64 bit string (update: which could be as 16 character hex string or char vector, 64 character binary string or char vector, or logical as I can derive all of those from the input) into the corresponding 64-bit integer?
(If I have to, I can create a conversion function that converts the string / char to logical, and uses an array of 64 uint64 constants (2^0, 2^1, ... 2^63) and multiplies them by the logical mask - but is there something built-in with less steps (and better efficiency) that I can use?
For example:
An input could be:
'F3 00 79 00 00 1E FF FF'
Which could also be represented with binary:
'1111001100000000011110010000000000000000000111101111111111111111'
Ultimately it should be a uint64 value of:
17510128392125480959
Using the built-in MATLAB functions, I get a warning and an incorrect answer:
uint64( hex2dec('F3007900001EFFFF') )
Or, alternately:
uint64( bin2dec('1111001100000000011110010000000000000000000111101111111111111111') )
As you can see, they both result in an answer of 17510128392125480960 which is 1 off from the desired answer.
0 Comments
Answers (2)
Walter Roberson
on 23 Jan 2023
F3str = 'F3007900001EFFFF'
F3 = swapbytes(typecast(uint8(sscanf(F3str, '%02x')), 'uint64'))
%crosscheck
dec2hex(F3)
isequal(dec2hex(F3), F3str)
1 Comment
Walter Roberson
on 23 Jan 2023
If needed, you can add automatic padding into the code
F3str = 'F300900001EFFFF' %shorter
F3 = swapbytes(typecast(uint8(sscanf([repmat('0', 1, 16-length(F3str)), F3str], '%02x')), 'uint64'))
%crosscheck
dec2hex(F3, 16)
isequal(dec2hex(F3), F3str)
Jan
on 17 Jan 2023
Edited: Jan
on 17 Jan 2023
The question explains with many details, where the numbers are coming from. It would be more useful to post a set aof available input data as Matlab code. So what do you call "integer based" and "64-bit string"? Which format does the input have?
Assuming that a "64 bit string" ist a char vector:
in = char('0' + randi([0,1], 1, 64))
format long
out = BinToUINT64(in)
function out = BinToUINT64(in)
d = uint64(in - '0'); % Vector of doubles containing the bits
out = sum(d .* bitshift(uint64(1), 63:-1:0), 'native');
% Or more flexible:
% out = sum(d .* bitshift(uint64(1), numel(in)-1:-1:0), 'native');
end
% Alternatively:
function out = BinToUINT64(in)
v = bitshift(uint64(1), numel(in)-1:-1:0);
out = sum(v(in == '1'), 'native');
end
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!