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].
Related
I have a vector of cells (say, size of 50x1, called tokens) , each of which is a struct with properties x,f1,f2 which are strings representing numbers. for example, tokens{15} gives:
x: "-1.4343429"
f1: "15.7947111"
f2: "-5.8196158"
and I am trying to put those numbers into 3 vectors (each is also 50x1) whose type is float. So I create 3 vectors:
x = zeros(50,1,'single');
f1 = zeros(50,1,'single');
f2 = zeros(50,1,'single');
and that works fine (why wouldn't it?). But then when I try to populate those vectors: (L is a for loop index)
x(L)=tokens{L}.x;
.. also for the other 2
I get :
The following error occurred converting from string to single:
Conversion to single from string is not possible.
Which I can understand; implicit conversion doesn't work for single. It does work if x, f1 and f2 are of type 50x1 double.
The reason I am doing it with floats is because the data I get is from a C program which writes the some floats into a file to be read by matlab. If I try to convert the values into doubles in the C program I get rounding errors...
So, (after what I hope is a good question,) how might I be able to get the numbers in those strings, at the right precision? (all the strings have the same number of decimal places: 7).
The MCVE:
filedata = fopen('fname1.txt','rt');
%fname1.txt is created by a C program. I am quite sure that the problem isn't there.
scanned = textscan(filedata,'%s','Delimiter','\n');
raw = scanned{1};
stringValues = strings(50,1);
for K=1:length(raw)
stringValues(K)=raw{K};
end
clear K %purely for convenience
regex = 'x=(?<x>[\-\.0-9]*),f1=(?<f1>[\-\.0-9]*),f2=(?<f2>[\-\.0-9]*)';
tokens = regexp(stringValues,regex,'names');
x = zeros(50,1,'single');
f1 = zeros(50,1,'single');
f2 = zeros(50,1,'single');
for L=1:length(tokens)
x(L)=tokens{L}.x;
f1(L)=tokens{L}.f1;
f2(L)=tokens{L}.f2;
end
Use function str2double before assigning into yours arrays (and then cast it to single if you want). Strings (char arrays) must be explicitely converted to numbers before using them as numbers.
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.
The C-Code is stored in a DLL. I can load the DLL in MATLAB with the loadlibrary function. I am having trouble passing the wchar_t*[] parameter to the function. I do not know how to create this data type in MATLAB. Does anyone know how to create this type to pass to the calllib function?
MATLAB Code:
loadlibrary('test.dll', 'test.h');
str = '0';
ptr = libpoiner('voidPtrPtr', [int8(str) 0])
calllib('test.dll', 'testFunction', ptr) %this parameter does not match the wchar*[] type
outVal = ptr.Value
C-Code:
void testFunction(wchar_t* str[])
{
str[0] = L"test";
}
Output:
MATLAB allows the function to complete. The outVal variable is filled with garbage values.
If you are able to modify the C header files, you may try the following:
Adjust the header file to convert all wchar_t * to unsigned short *.
On the MATLAB side, the corresponding type would then be a uint16 array.
You could then typecast the uint16 array to char.
I figured it out. I changed the MATLAB code to the following:
loadlibrary('test.dll', 'test.h');
str = '0';
ptr = libpoiner('voidPtrPtr', [uint16(str) 0])
calllib('test.dll', 'testFunction', ptr) %this parameter does not match the wchar*[] type
outVal = ptr.Value
expectedOutput = char(outVal); %convert to ASCII
It outputs the values in decimal which confused me. When I converted them to ASCII, everything made sense.
I am trying to perform a modulo operation in MATLAB, and I'm not sure how to convert the input variable to the correct data type for the modulo operation to complete.
Here is what I have:
sequence = 0;
....
sequence = sequence + 1;
if (modp(sequence, 3) == 0)
....
In C-ish, I'm looking to perform if (sequence % 3 == 0).
MATLAB complains that there is no modp operation for a double, and that I must use an int. However, the documentation doesn't say which integer format I need to use (i.e., int8, int64, et cetera) and none of those integer formats work.
What am I doing wrong?
Did you realize you are using a function of the "symbolic toolbox"? I don't see any advantage in this case thus simply use mod(a,b) from Matlab (there is also a fixed point mod(a,b) and symbolic mod(a,b), don't confuse them)
http://www.mathworks.de/de/help/matlab/ref/mod.html
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.