Why are MATLAB uint8 value and uint16 values different - matlab

I have declared a uint8 value as A = [4, 8, 16, 32]; and I casted to the value B = typecast(uint8(A), 'uint16'), but the answer is 2052 8208 I would be very thankful if anyone could help me to understand the reason behind it.

You are probably expecting for Matlab to put your uint8 values just into uint16 variables. This is not what the typecast function is doing. It will preserve the number of bytes from the input to the output. So in your example, it merges the bit representation of 4 and 8 into a uint16 number and equivalently also 16 and 32.
So the binary representation of 4 is 00000100 and of 8 is 00001000 and merged together (to a 16bit number) they give 0000100000000100, which is 2052.

MATLAB's typecast function converts the data type without changing the underlying data. In other words, it doesn't changes the underlying memory representation of the data structure, and simply treats it as a uint16 instead of uint8.
In your case, you want to preserve to original values of your data after casting. Therefore, you do want MATLAB to change the memory representation of the data structure.
There are two ways to perform this type of casting:
-using cast function
B = cast(uint8(A), 'uint16');
-using a direct call to uint16 function:
B = uint16(A);
result:
B =
4 8 16 32

Related

How to convert uint8 to int in Matlab?

I have converted the image from RGB to grayscale and have the image-matrix in uint8. I'm trying to make some image processing with convolution which means that I want to use the values as int when I'm summing up everything. So, how can I convert from uint8 to int in Matlab?
Matlab support multiple integer formats. The main difference is the required space in memory and if the sign (+ or -) is used.
For example, uint8 means that the integer is unsigned and that it uses 8 bit to store the value. The number of used bits determines the maximal value. The uint8 can store a number between 0 and 2^8-1.
You can find a whole list of all supported integer here
If you would like to convert your uint8 into another format you can just write the desired format as a function and pass the value as parameter:
I2 = uint16(I);
In matlab you can use double type.
for example type cast with:
I2=double(I);
It is easy to understand that you can use
int8(I)
int16(I)
too.

Error -> Colon operands must be in the range of the data type. No sense

In the code below image index range only accept to deal with int16 however I can't find a proper explanation for this case. In the same code, you can notice if I change the data type to int8 for same value error will present.
K>> t2 = int8(t)
t2 =
int8
45
K>> I2 = flt_rot(t:end,:);
K>> I2 = flt_rot(t2:end,:);
Error using :
Colon operands must be in the range of the data type.
Why did this happen?
To understand this problem, first a little background:
MATLAB has a rather unique behavior with respect to numeric values of different types. Originally, MATLAB only used double-precision floating point values (double). At some point it became possible to store arrays of other types, but it was not possible to use those for much. It was not until MATALB 7.0 or so that arithmetic with non-doubles was possible (I'm a bit hazy exactly when that was introduced). And these operations are still a bit "awkward", if you will.
For one, MATLAB does not allow operations with mixed types:
>> int8(4)+int16(6)
Error using +
Integers can only be combined with integers of the same class, or scalar doubles.
Note that error message: "scalar doubles". The one exception to mixed types is that any operation is possible if one of the operands is a scalar double.
Another thing to note is that any operation with a non-double type and a double type results in values of the non-double type:
>> int8(4)+6
ans =
int8
10
The color operator (:) is no exception:
>> int8(4):6
ans =
1×3 int8 row vector
4 5 6
Finally, the last thing to know to understand this problem is that end is a function that returns a double scalar value (yes, it really is a function, albeit a very special one, see help end).
If you have an array flt_rot that is 200x300, end in the first index returns 200. That is, flt_rot(t2:end,:) is the same as flt_rot(t2:200,:). Since t2 is a int8 type:
>> t2=int8(45);
>> t2:200
Error using :
Colon operands must be in the range of the data type.
The solution to your problem is to not use numeric values of type other than double for anything except in large data sets where the amount of memory used matters. For indexing, using an integer is not going to give you any speedup over using doubles, but will give you lots of other problems. There is a reason that the default values are always doubles.
This will work:
I2 = flt_rot(double(t2):end,:);

Type casting in Matlab

What is the proper way to cast data types in Matlab?
I have my data stream (instrument data) as undifferentiated elements of a uint8 array, which I want to cast into a composite data types, like for instance a 3-byte, 24-bit integer, or a 3-byte, 3 character string.
I normally do this on the fly specifying a format in fread(), but once the data is already in a uint8 array, is typecast() the proper way to go about it, or is there a nicer syntax?
As I know, there is not any data type for integer 3 or 24 bytes (see documentaion). However, about casting from uint8 to string, it can be done by num2str function (like num2str(uint8(123)). Also if you want get a 2 char string (from left) you can do it by num2str(uint8(123))(end-1:end);

Coercion between uint types

I have a problem in general when Matlab is unable to work out how to logically store values of differing uint types. For example:
tempC = {uint8(5) uint16(16)}
For me, it seems logical to be able to convert this into a matrix of type integer using cell2mat(tempC), which returns
>> cell2mat(tempC)
Error using cell2mat (line 45)
All contents of the input cell array must be of the same data type.
Of course, I understand that the truncation behaviour of integers depends on the type (e.g. uint8 forces all numbers greater than 255 to be 255), however, in this case I would say it would be safe enough to output cell2mat(tempC) with uint16 type. Does anyone have any ideas on how this can be achieved in general?
cell2mat will not work if there are cells of differing types. cell2mat merges the cells together into a matrix, but matrix elements in MATLAB must all share the same type. This is fundamental to how MATLAB works with numeric matrices. If you didn't have all of the same type, then you should use cell arrays... which is what they are for.
However, one thing I can suggest is figure out the type of all of the elements in your matrix, then iterate through each cell and cast them all to be the largest precision type. You can then use cell2mat on this intermediate result to complete the conversion. However, what I have written doesn't actually require calling cell2mat in the end. You'll see later.
Something like this:
%// Get all of the possible types in the array
types = unique(cellfun(#class, tempC, 'uni', 0));
%// Figure out the largest type
vals = cellfun(#(x) double(intmax(x)), types);
[~,ind_max] = max(vals);
%// Cast all values to this type
class_max = types{ind_max};
tempC = cellfun(#(x) cast(x, class_max), tempC);
We first determine all of the possible classes that your cell array contains. We then figure out which of the types is the largest of them all. This can be done by using intmax on each of the types. intmax tells you the largest possible integer that is available for that type, so we basically choose the type that generates the largest possible integer. Take note that I had to cast to double as the output of intmax certainly does output the maximum associated for an integer type, but the output is also cast to that type. This is required so that I can combine all of these elements into an array of the same type - double.
Once we get the type producing the maximum possible integer, we then go through the cell array and cast all of the values to this type. Take note that I used cellfun for the final call which outputs a numeric array - no need to use cell2mat here. In the last line of code, I use cast to cast all of the numbers in the cell array to this type, thus achieving "coercion".
Using your example array, this is what I get, as well as what class the final array is in:
>> tempC
tempC =
5 16
>> class(tempC)
ans =
uint16

How do I interpret two 32-bit unsigned integers as a 64-bit floating-point ("double") value?

My knowledge of matlab is very limited, so I'll use more general terms to explain my problem:
We have a recording system that samples variables in an embedded system in realtime, and delivers the recorded data as matlab files for analysis.
My problem is that if a recorded variable is a "double" (more specifically a 64-bit, IEEE 754-1985, floating point value), the result is delivered as two unsigned 32-bit integers, and I have no idea how to turn it back into a floating-point value in matlab.
For example, if I record the variable SomeFloat, which is a double, I will get the recorded data as two sets of data, SomeFloat1 and SomeFloat2. Both are unsigned, 32-bit integers. SomeFloat1 contains the 32 most significant bits of SomeFloat, and SomeFloat2 contains the 32 least significant bits.
I was hoping to find an existing function for converting it back do a double, I mean something like:
MyDouble = MyDreamFunction(SomeFloat1, SomeFloat2)
I have not been able to find MyDreamFunction, but being new to matlab, I'm not really sure where to look...
So, does anyone know of a simple way to do this?
I think you want typecast (convert datatypes without changing underlying data):
>> x1 = uint32(7346427); %// example uint32 value
>> x2 = uint32(1789401); %// example uint32 value
>> typecast([x2 x1],'double')
ans =
1.4327e-306
>> typecast([x1 x2],'double')
ans =
3.7971e-308