Numeric and byte order (endian) conversions in MATLAB
Contents
- Creating an integer variable
- Destructive casting - I
- Destructive casting - II
- Non-destructive casting
- Converting an integer to a sequence of bytes
- Converting a floating-point value to a sequence of bytes
- Converting a sequence of bytes to an integer
- Checking the Endianness of the system
- Little-endian and Big-endian conversions
- Help on functions
Creating an integer variable
Say I want to create a variable of type uint16, with value 100.
Method 1
val1 = uint16(100);
Method 2
val2 = cast(100, 'uint16');
Method 3
val3 = zeros(1,1,'uint16'); val3(1) = 100; whos val1 val2 val3
Name Size Bytes Class Attributes val1 1x1 2 uint16 val2 1x1 2 uint16 val3 1x1 2 uint16
Incorrect method
The following won't work, since val4 will be reinitialized to have the type of the number '100', i.e., it will be a double.
val4 = zeros(1,1,'uint16'); val4 = 100; whos val4
Name Size Bytes Class Attributes val4 1x1 8 double
Destructive casting - I
If I have a variable of type uint16 and would like to convert it to a uint8, I can use the CAST or UINT8 commands.
First create a variable of type uint16
aval = uint16(10000);
Conversion to int16 is safe, since 10000 is within the valid range for an int16.
bval = int16(aval)
bval = 10000
Convert to uint8 is not safe since the 10000 doesn't fit in the new type. Hence, the value gets clipped.
cval = uint8(aval)
cval = 255
It is not possible to recover the original aval from the uint8 variable cval
new_aval = uint16(cval); aval,new_aval
aval =
10000
new_aval =
255
Destructive casting - II
The behavior of CAST and functions like UINT16 or INT8 can be frustrating if I have a signed integer that I want to treat as an unsigned number, or vice versa (i.e., I want to convert to/from the two's-complement representation of the number).
aval = int16(-200); bval = uint16(aval); whos aval bval, bval
Name Size Bytes Class Attributes
aval 1x1 2 int16
bval 1x1 2 uint16
bval =
0
bval is 0 since the allowable range for a uint16 is [0,65535], and the value of -100 gets clipped to 0. Hence, it is not possible to recover the original number, even though aval and bval have the same size (two bytes):
new_aval = int16(bval); aval, new_aval
aval =
-200
new_aval =
0
Non-destructive casting
The way to do non-destructive casting is with the TYPECAST command.
aval = int16(-200); bval = typecast(aval, 'uint16'); whos aval bval, bval
Name Size Bytes Class Attributes aval 1x1 2 int16 bval 1x1 2 uint16 bval = 65336
Now convert back from uint16 to int16
new_aval = typecast(bval, 'int16');
aval, new_aval
aval = -200 new_aval = -200
Converting an integer to a sequence of bytes
Say I want to convert a mulitbyte number to a sequence of bytes (e.g., I want to save the data in a custom binary format, or want to send it over a communications channel that only takes a sequence of bytes).
Make a 4-byte signed integer
aval = int32(-314159);
whos aval, aval
Name Size Bytes Class Attributes
aval 1x1 4 int32
aval =
-314159
Convert the 4-byte integer to a sequence of four unsigned bytes
bval = typecast(aval, 'uint8'); whos bval, bval
Name Size Bytes Class Attributes bval 1x4 4 uint8 bval = 209 52 251 255
Now convert from the sequence of bytes back to a multibyte value
new_aval = typecast(bval, 'int32');
aval, new_aval
aval =
-314159
new_aval =
-314159
Converting a floating-point value to a sequence of bytes
Create an 8-byte floating point value (i.e., of type double)
aval = 3.14159; % equivalent to double(3.14159) whos aval, aval
Name Size Bytes Class Attributes
aval 1x1 8 double
aval =
3.1416
This becomes a sequence of 8 unsigned bytes
bval = typecast(aval, 'uint8'); whos bval, bval
Name Size Bytes Class Attributes bval 1x8 8 uint8 bval = 110 134 27 240 249 33 9 64
Now convert back:
new_aval = typecast(bval, 'double');
aval, new_aval
aval =
3.1416
new_aval =
3.1416
Converting a sequence of bytes to an integer
Sometimes I have a sequence of bytes that I want to convert to a multibyte integer. This example shows how to go from an array of four bytes to a uint32.
Define a byte array of length 4
byteArray = zeros(1,4,'uint8'); byteArray(1) = 2; byteArray(2) = 1; whos byteArray, byteArray
Name Size Bytes Class Attributes
byteArray 1x4 4 uint8
byteArray =
2 1 0 0
Another way of specifying byteArray
byteArray = uint8([2 1 0 0]);
Now convert to a uint32 (the bytes will be interpreted in Little-endian order on my system).
integerValue = typecast(byteArray, 'uint32'); whos integerValue, integerValue
Name Size Bytes Class Attributes
integerValue 1x1 4 uint32
integerValue =
258
Checking the Endianness of the system
The COMPUTER command returns the current endian-ness (the value of endian is 'L' if the system is Little-endian, and 'B' if it is Big-endian).
[computerType, maxSize, endian] = computer;
isLittleEndian = (endian == 'L')
isLittleEndian =
1
Another way of testing the endianness
testNumber = uint32(1);
byteSeq = typecast(testNumber, 'uint8');
isLittleEndian = (byteSeq(1) == 1)
isLittleEndian =
1
Little-endian and Big-endian conversions
The TYPECAST operator makes it easy to do byte-order conversions, such as from Little-endian to Big-endian. For example, I may need to save to a binary file that needs to be read on big-endian system, or may need to send data over a communications channel that assumes big-endian representation.
Create a little-endian number (I know it is little-endian since my computer is a Little-endian system; see the section on checking endianness).
leNumber = uint32(258);
Get the bytes in the 32-bit little-endian number (note that the leftmost byte is the least-significant one).
byteSeq = typecast(leNumber, 'uint8')
byteSeq =
2 1 0 0
See each byte as a binary number (each row is one byte)
dec2bin(byteSeq,8)
ans = 00000010 00000001 00000000 00000000
There are two ways to convert the little-endian value to a big-endian value
Method 1: Use the SWAPBYTES command
beNumber = swapbytes(leNumber)
newByteSeq = typecast(beNumber, 'uint8')
beNumber =
33619968
newByteSeq =
0 0 1 2
Method 2: Do the conversion myself
newByteSeq = byteSeq(end:-1:1)
beNumber = typecast(newByteSeq, 'uint32')
newByteSeq =
0 0 1 2
beNumber =
33619968
Help on functions
help class
CLASS Create object or return object class.
C = CLASS(OBJ) returns the class of the object OBJ.
Possibilities are:
double -- Double precision floating point number array
(this is the traditional MATLAB matrix or array)
single -- Single precision floating point number array
logical -- Logical array
char -- Character array
cell -- Cell array
struct -- Structure array
function_handle -- Function Handle
int8 -- 8-bit signed integer array
uint8 -- 8-bit unsigned integer array
int16 -- 16-bit signed integer array
uint16 -- 16-bit unsigned integer array
int32 -- 32-bit signed integer array
uint32 -- 32-bit unsigned integer array
int64 -- 64-bit signed integer array
uint64 -- 64-bit unsigned integer array
<class_name> -- Custom object class
<java_class> -- Java class name for java objects
All other uses of CLASS must be invoked within a constructor method,
in a file named <class_name>.m in a directory named @<class_name>.
Further, 'class_name' must be the second argument to CLASS.
O = CLASS(S,'class_name') creates an object of class 'class_name'
from the structure S.
O = CLASS(S,'class_name',PARENT1,PARENT2,...) also inherits the
methods and fields of the parent objects PARENT1, PARENT2, ...
O = CLASS(struct([]),'class_name',PARENT1,PARENT2,...), specifying
an empty structure S, creates an object that inherits from one or
more parent classes, but which does not have any additional fields
not inherited from the parents.
See also ISA, SUPERIORTO, INFERIORTO, STRUCT.
Overloaded methods:
scribehandle/class
serial/class
digitalio/class
analogoutput/class
analoginput/class
visa/class
udp/class
tcpip/class
icgroup/class
icdevice/class
gpib/class
doc class
help cast
CAST Cast a variable to a different data type or class.
B = CAST(A,NEWCLASS) casts A to class NEWCLASS. A must be convertible to
class NEWCLASS. NEWCLASS must be the name of one of the builtin data types.
Example:
a = int8(5);
b = cast(a,'uint8');
See also CLASS.
Overloaded methods:
ccspointer/cast
ccsnumeric/cast
ccsenum/cast
ccsbitfield/cast
darray/cast
doc cast
help typecast
TYPECAST Convert datatypes without changing underlying data.
Y = TYPECAST(X, DATATYPE) convert X to DATATYPE. If DATATYPE has
fewer bits than the class of X, Y will have more elements than X. If
DATATYPE has more bits than the class of X, Y will have fewer
elements than X. X must be a scalar or vector. DATATYPE must be one
of 'UINT8', 'INT8', 'UINT16', 'INT16', 'UINT32', 'INT32', 'UINT64',
'INT64', 'SINGLE', or 'DOUBLE'.
Note: An error is issued if X contains fewer values than are needed
to make an output value.
Example:
X = uint32([1 255 256]);
Y = typecast(X, 'uint8');
On little-endian architectures Y will be
[1 0 0 0 255 0 0 0 0 1 0 0]
See also CLASS, CAST, SWAPBYTES.
Overloaded methods:
darray/typecast
doc typecast
help swapbytes
SWAPBYTES Swap byte ordering, changing endianness.
Y = SWAPBYTES(X) reverses the byte ordering of the matrix X,
converting little-endian values to big-endian (and vice versa).
Example:
X = uint16([0 1 128 65535]);
Y = swapbytes(X);
Y will have the following uint16 values:
[0 256 32768 65535]
Examining the output in hex notation shows the byte swapping:
format hex
X, Y
format
See also TYPECAST.
Overloaded methods:
darray/swapbytes
doc swapbytes
