Numeric and byte order (endian) conversions in MATLAB
- 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
Say I want to create a variable of type uint16, with value 100.
val1 = uint16(100);
val2 = cast(100, 'uint16');
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
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
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
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
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
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
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
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
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
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)
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
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
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
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
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