I read from the serial port 4 bytes and I want to create a Matlab
function to convert them into a float number
for example: if I read A=[65 240 0 0] I must have 30 according to
IEEE754 standard.
- I have used Simulink block "byte unpack" but i have problems. in fact
I should read over 18 parameters. each parameters is 4 bytes
array.then I should use 18 byte unpack.
By default, Matlab will use double precision to store any new value which doesn't have a type specified. If you know you are reading byte, then the best is to collect them directly as uint8 (the unsigned byte type of Matlab) if you can (in your call to fread or equivalent).
If you cannot collect them directly as uint8 then cast them as such then use the typecast function.
A = [65 240 0 0] ; %// Collected bytes
A = uint8(A) ; %// cast them to "uint8" if they are not already
Afloat = typecast( A , 'single') ; %// cast the 4 bytes as a 32 bit float
wait a minute:
Afloat =
8.6186862e-41
oops, it seems the byte ordering used by your collection mechanism is the opposite as the one used by Matlab. No problem, you can just change the endianness by "flipping" the byte array.
So instead, use:
>> Afloat = typecast( fliplr(A) , 'single')
Afloat =
30
success :)
You can also look at the function swapbytes to manage the endianess.
To avoid reinventing the wheel, simply use
A = fread(obj,size,'precision')
as described in documentation
For example,
[A,count] = fread(obj, 18, 'float32');
should read 18 4 byte floats.
Related
I'm trying to print scalar as it would look like if it was int32. That is, if I have 2532063508, if I write it in 4 bytes and read as int32, I would read -1762903788.
using int32 function in Matlab didn't work, because the way it works is, values outside the range [-2^31,2^31-1] map to the nearest endpoint.
So I tried to use typecast:
typecast(uint32(2532063508), 'int32')
works perfectly, but if I write e.g. -1 there, uint32() returns 0 so it fails.
P.S. I want it to work for signed integers as input as well, that is, for -1 it should return -1
any suggestions?
You can do calculations in int64 then convert to uint32:
f = #(x)typecast(uint32(mod(int64(x),int64(2)^32)),'int32');
Or
function y = f(x)
y = typecast(uint32(mod(int64(x),int64(2)^32)),'int32');
end
So f([-1, 2532063508]) returns [-1, -1762903788].
I am looking to compare arrays of type uint8 in Matlab and wondering if there is a function to compare them. So, I have something like:
par_id = uint8([0x00 0x00 0x4d 0x4f 0x54 0x50 0x41 0x52])
fileID = fopen(file);
# Here I read the first 8 bytes from a file
magic = uint8(fread(fileID, 8, 'uint8'));
I thought I could do a strcmp or something like that but that fails:
strcmp(uint8(magic'), par_id) // returns 0
I can do a for loop and compare them element by element but is there a built-in function that I can use?
Use isequal. It will test the size and contents of what you want to compare, and ignores the type.
I have a hill cipher encryption script to execute image. But I want this to be a script to execute char 8 bits (.txt). Please help me, thank you :)
I=imread('E:\Lena.bmp');
I=rgb2gray(I);
I2=I(:);
n=size(I2);
K=[2 5;3 12];
d=mod(det(K),256);
if(d==0)
disp('determinant should not be 0');
return
end
if(gcd(d,256)>1)
disp('determinant should be coprime integers with 256');
return
end
%encryption process
for i=(1:2:n)
x=[I2(i);I2(i+1)];
x=mod(K*double(x),256);
CI(i)=x(1);
CI(i+1)=x(2);
end
I3=reshape(CI,[256 256]);
I3=uint8(I3);
imshow(I3)
imwrite(I3,'encryption.bmp','bmp');
The following answer does not comment on the encryption method itself but only on how to get the needed input and how to process the output.
The only thing: The line defining the for-loop should be i=(1:2:n-1). Note that you need to use n-1 because later you try to access I2(i+1) and in Matlab the first index is 1.
The output of rgb2gray is of type uint8. So basically what we need is to read the text file with fscanf and then convert char to uint8. Now the format of I is the same as you would use an image as input.
F = fopen('data.txt','r');
D = fscanf(F,'%c');
fclose(F);
I = uint8(D);
After the encryption process, we can write the data back into a file with fprintf after converting to uint8 and char.
F = fopen('data_encrypted.txt','w');
fprintf(F,'%c',char(uint8(CI)));
fclose(F);
Say I have an array that contains the following elements:
1.0e+14 *
1.3325 1.6485 2.0402 1.0485 1.2027 2.0615 1.7432 1.9709 1.4807 0.9012
Now, is there a way to grab 1.0e+14 * (base and exponent) individually?
If I do arr(10), then this will return 9.0120e+13 instead of 0.9012e+14.
Assuming the question is to grab any elements in the array with coefficient less than one. Is there a way to obtain 1.0e+14, so that I could just do arr(i) < 1.0e+14?
I assume you want string output.
Let a denote the input numeric array. You can do it this way, if you don't mind using evalc (a variant of eval, which is considered bad practice):
s = evalc('disp(a)');
s = regexp(s, '[\de+-\.]+', 'match');
This produces a cell array with the desired strings.
Example:
>> a = [1.2e-5 3.4e-6]
a =
1.0e-04 *
0.1200 0.0340
>> s = evalc('disp(a)');
>> s = regexp(s, '[\de+-\.]+', 'match')
s =
'1.0e-04' '0.1200' '0.0340'
Here is the original answer from Alain.
Basic math can tell you that:
floor(log10(N))
The log base 10 of a number tells you approximately how many digits before the decimal are in that number.
For instance, 99987123459823754 is 9.998E+016
log10(99987123459823754) is 16.9999441, the floor of which is 16 - which can basically tell you "the exponent in scientific notation is 16, very close to being 17".
Now you have the exponent of the scientific notation. This should allow you to get to whatever your goal is ;-).
And depending on what you want to do with your exponent and the number, you could also define your own method. An example is described in this thread.
Im not sure if Im missing something simple but the following code fails (a and b are meant to be the same):
a=single(2147483584)
f=fopen('test','wb');
fwrite(f,a,'int32')
fclose(f);
f=fopen('test','rb');
b=fread(f,inf,'int32');
fclose(f)
a
b
with output:
a =
2.1475e+009
b =
-2.1475e+009
and the following code succeeds:
a=single(2147483583)
f=fopen('test','wb');
fwrite(f,a,'int32')
fclose(f);
f=fopen('test','rb');
b=fread(f,inf,'int32');
fclose(f)
a
b
with output:
a =
2.1475e+009
b =
2.1475e+009
Does anyone know why?
I don't know Matlab well, but it seems fairly clear what's happening here. You're converting a to a float and then storing the result of that conversion as a 32-bit signed integer. But the nearest single-precision IEEE 754 float to the integer 2147483584 is 2147483648.0, or 2**31. A 32-bit integer can only represent values in the range [-2**31, 2**31-1], so it looks as though when you write this value as an integer, it gets wrapped modulo 2**32 to give -2**31 instead of 2**31.
In contrast, the nearest single-precision float to 2147483583 is 2147483520.0, which does fit in a 32-bit integer.