The code I'm reading has a line:
someData = nan(3, 4, 5, "single")
I can't find the documentation for the "nan" function, but this code appears to generate a 3x4x5 matrix of NaN. However, I don't know what "single" does. Replacing it with a random other string gets "error: NaN: invalid data type specified", and replacing it with "double" appears to give the same result. What is the function of the "single"?
It makes the resulting matrix of nan a matrix that is of the single-precision data type which contains single-precision floating-point numbers. If you want single precision, you need to specify this explicitly, otherwise Octave and MATLAB will use double-precision by default.
You can check the class of the output using class.
class(nan(3, 4, 5, 'single'))
% 'single'
class(nan(3, 4, 5))
% 'double'
As far as looking the same, they will look the same until you start trying to store numbers that exceed the range of numbers that can be represented with single-precision floating point representation. This is because single precision numbers use half the amount of memory that double precision numbers do.
a = nan(1, 1, 'single');
a(1) = 1e-64
% 0
b = nan(1, 1);
b(1) = 1e-64
% 1.000e-64
Also if we inspect the variables with whos we can confirm the size difference.
a = nan(1,1,'single');
b = nan(1,1)
whos('a', 'b')
% Variables in the current scope:
%
% Attr Name Size Bytes Class
% ==== ==== ==== ===== =====
% a 1x1 4 single
% b 1x1 8 double
Related
Say I have a row vector defined as follows:
x = [5 6.7 8.9]
The above code results in a row vector with all the elements being typecasted as floating points(including the 5 in the 1st index).
x =
5.0000 6.7000 8.9000
Is there any way I can prevent the typecasting of the 5 (present in the first place), i.e. is there any way I can get my vector as follows:
x =
5 6.7000 8.9000
without the four decimal points after the 5.
In Matlab and Octave, double is the default value for all numeric values, even if some of those values might be whole numbers (integers). And for numeric arrays, all elements must be of the same type.
In general, you should just leave all your numeric values as doubles, and use formatting controls (like those provided by printf() and its friends) to display them how you want.
In this case, you could do something like:
x = [5 6.7 8.9];
printf('%d %.04f %.04f\n', x);
Or to be more flexible:
printf('%g ', x); printf('\n');
I have two matrices. Matrix A(2048,64) and matrix B(10000,64). Values in each element of these matrices is a binary bit, so each row is a representation of a 64-bit binary value, so each row of the matrix has a magnitude between 2^63 and 2^0; Most Significant Bit to Least Significant Bit, respectively.
Problem:
For each row of A I want to find the value in B which is the closest to it in an absolute, numeric sense.
Consider A(i,1:64) being a binary representation of decimal value Xi, and B(j,1:64) a binary representation of decimal value Yj. So at the first step I want to find the best j such that X1 or A(1,1:64) has the closest numeric value to the element at Yj, i.e. abs(X1-Yj) is minimized among all possible values for j.
The below image, brought from here, describes my problem rather well, but the difference is that each of my values are contained in a row of a matrix containing 64 elements.
I tried to convert the 64-bit values to decimal, however dec2bin supports values up to 56-bit only.
You can divide your 64-bit number into two 32-bit pieces, b1 and b2, convert them to decimal values d1 and d2, then combine them into a uint64 value that has enough precision to hold the result.
bin2uint64 = #(b) uint64(bin2dec(b(:,1:32)))*(2^32) + uint64(bin2dec(b(:,33:64)));
(This assumes that you have your data in the same format required by bin2dec, i.e. a vector of char. If you have a vector of numeric values, just add in a b = char(b+'0');)
Given an initial value
>> b = 1100110010111100101101111010100010101010010011010010000110011010
>> d = bin2uint64(b)
d = 14752868414398472602
>> r = dec2bin(d, 64)
r = 1100110010111100101101111010100010101010010011010010000110011010
>> any(b-r)
ans = 0
Since b-r gives all zeros, the values are identical. You can pass the entire nx64 matrix as b and it will convert all of the values at once.
>> bin2uint64(char(randi([0 1], 20, 64) + '0'))
ans =
4169100589409210726
8883634060077187622
15399652840620725530
12845470998093501747
14561257795005665153
1133198980289431407
13360302497937328511
563773644115232568
8825360015701340662
2543400693478304607
11786523850513558107
8569436845019332309
2720129551425231323
5937260866696745014
4974981393428261150
16646060326132661642
5943867124784820058
2385960312431811974
13146819635569970159
6273342847731389380
You'll notice that I manually converted my random array to char. Assuming your input is numeric, you'll have to convert it first:
Achar = char(A + '0');
Yes, this is a pain, MATLAB should have included a destination type parameter in bin2dec, but they didn't. Now you can use your linked solution to find the matchings.
Converting your values:
Assuming your matrices A and B contain the numeric values 0 and 1, you can easily convert the rows to uint64 data types without precision loss using the bitset and sum functions (and bsxfun for a small efficiency boost):
result = sum(bsxfun(#(bit, V) bitset(uint64(0), bit, V), 64:-1:1, A), 2, 'native');
Compared to the solution from beaker, this one is over 4 times faster for a 10,000 row matrix:
% Sample data:
A = randi([0 1], 10000, 64);
% Test functions:
bin2uint64 = #(b) uint64(bin2dec(b(:,1:32)))*(2^32) + uint64(bin2dec(b(:,33:64)));
beaker_fcn = #(A) bin2uint64(char(A+'0'));
gnovice_fcn = #(A) sum(bsxfun(#(b, V) bitset(uint64(0), b, V), 64:-1:1, A), 2, 'native');
% Accuracy test:
isMatch = isequal(beaker_fcn(A), gnovice_fcn(A)); % Return "true"
% Timing:
timeit(#() beaker_fcn(A))
ans =
0.022865378234183
timeit(#() gnovice_fcn(A))
ans =
0.005434031911843
Computing nearest matches:
You provide a link to some solutions for finding the nearest matches for A in B. However, the fact that you are using unsigned integer types requires some modification. Specifically, order matters when subtracting values due to integer overflow. For example uint64(8) - uint64(1) gives you 7, but uint64(1) - uint64(8) gives you 0.
Here's the modified solution for unsigned integers, applied to the sample data you provide:
A = uint64([1 5 7 3 2 8]);
B = uint64([4 12 11 10 9 23 1 15]);
delta = bsxfun(#(a, b) max(a-b, b-a), A(:), reshape(B, 1, []));
[~, index] = min(delta, [], 2);
result = B(index)
result =
1×6 uint64 row vector
1 4 9 4 1 9 % As expected!
I have sparse matrix A which I need to convert to complex-sparse matrix by setting its imaginary part to zero.
A = sprand(3,3,0.5);
A_c = complex(A,0);
However, this throws me an error that A should be full.
Error using complex
Real input A must be numeric, real, and full.
Is there any work-around to achieve this?
When I first answered this question I did not consider the way complex sparse matrices are implemented in MATLAB. I tricked myself into the following answer.
Naive solution
You could apply complex() to each element of the matrix.
A_c = spfun(#(x)complex(x,0),A)
Here #(x)complex(x,0) denotes an anonymous function that applied to each element x of the matrix A returns a complex number with Re=x and Im=0. And spfun just returns a new sparse matrix produced by applying our anonymous function to the nonzero elements of the matrix A.
What happens is that this solution returns an object identical to the original matrix. The matrix A_c occupies the same number of bytes and is equal to the original matrix A.
>> whos A A_c
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
A 3x3 76 double
A_c 3x3 76 double
A comment from Florian Roemer made me reconsider my answer.
Explanation
The representation of sparse matrices in MATLAB is described in a paper by Gilbert, Moler and Schreiber published in 1991.
A real matrix is represented as a single vector of nonzero elements of the corresponding storage class (i.e. double or complex) stored in column-wise order plus an integer vector of indices of these elements in their respective columns plus an integer vector of indices of locations where new columns start. I.e. an m*n sparse matrix with k nonzero elements would occupy n*4 + k*12 bytes with 4 bytes for integers and 8 bytes to store reals as double precision. That is a 3x3 real sparse matrix with 5 nonzero entries occupies (4+5)*4+8*5 = 76 bytes.
A complex sparse matrix would have another real array for the imaginary parts of all nonzero entries of the matrix but only if at least one element has a nonzero imaginary part.
Consider
>> B = sprand(3,3,0.5)
B =
Compressed Column Sparse (rows = 3, cols = 3, nnz = 5 [56%])
(1, 1) -> 0.46883
....
>> B_c = B ; B_c(1,1) += 1e-100i
B_c =
Compressed Column Sparse (rows = 3, cols = 3, nnz = 5 [56%])
(1, 1) -> 4.6883e-01 + 1.0000e-100i
....
Now we have made MATLAB to allocate additional storage for the imaginary parts of each nonzero entry of the original matrix, even though only one of the entries has a nonzero imaginary part.
>> whos B B_c
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
B 3x3 76 double
c B_c 3x3 116 double
Now B_c is a proper complex sparse matrix that occupies
(4+5)*4 + 8 * 5 + 8 * 5 = 116 bytes
Conclusion
If you just need a sparse matrix with zero imaginary parts, then do nothing to the original matrix.
If you need a matrix that actually allocates storage for the complex entries and carries the complex attribute, then add a small imaginary value to at least one of the nonzero entries of the original matrix.
Matlab remark: I did not test this in actual Matlab but Octave is quite happy with this solution.
Is there a way to convert a decimal number between $0$ and $1$ that is not integer to base 4 in Matlab? E.g. if I put 2/5 I want to get 0.12121212... (with some approximation I guess)
The function dec2base only works for integers.
Listed in this post is a vectorized approach that works through all possible combinations of digits to select the best one for the final output as a string. Please note that because of its very nature of creating all possible combinations, it would be memory intensive and slower than a recursive approach, but I guess it could be used just for fun or educational purposes!
Here's the function implementation -
function s = dec2base_float(d,b,nde)
%DEC2BASE_FLOAT Convert floating point numbers to base B string.
% DEC2BASE_FLOAT(D,B) returns the representation of D as a string in
% base B. D must be a floating point array between 0 and 1.
%
% DEC2BASE_FLOAT(D,B,N) produces a representation with at least N decimal digits.
%
% Examples
% dec2base_float(2/5,4,4) returns '0.1212'
% dec2base_float(2/5,3,6) returns '0.101211'
%// Get "base power-ed scaled" digits
scale = b.^(-1:-1:-nde);
%// Calculate all possible combinations
P = dec2base(0:b^nde-1,b,nde)-'0';
%// Get the best possible combination ID. Index into P with it and thus get
%// based converted number with it
[~,idx] = min(abs(P*scale(:) - d));
s = ['0.',num2str(P(idx,:),'%0.f')];
return;
Sample runs -
>> dec2base_float(2/5,4,4)
ans =
0.1212
>> dec2base_float(2/5,4,6)
ans =
0.121212
>> dec2base_float(2/5,3,6)
ans =
0.101211
I have a vector containing the values 0, 1, 2 and 3. What I want to do is take the lower two bits from each set of 16 elements drawn from this vector and append them all together to get one uint32. Anyone know an easy way to do this?
Follow-up: What if the number of elements in the vector isn't an integer multiple of 16?
Here's a vectorized version:
v = floor(rand(64,1)*4);
nWord = size(v,1)/16;
sum(reshape([bitget(v,2) bitget(v,1)]',[32 nWord]).*repmat(2.^(31:(-1):0)',[1 nWord ]))
To refine what was suggested by Jacob in his answer and mtrw in his comment, here's the most succinct version I can come up with (given a 1-by-N variable vec containing the values 0 through 3):
value = uint32(vec(1:16)*4.^(0:15)');
This treats the first element in the array as the least-significant bit in the result. To treat the first element as the most-significant bit, use the following:
value = uint32(vec(16:-1:1)*4.^(0:15)');
EDIT: This addresses the new revision of the question...
If the number of elements in your vector isn't a multiple of 16, then the last series of numbers you extract from it will have less than 16 values. You will likely want to pad the higher bits of the series with zeroes to make it a 16-element vector. Depending on whether the first element in the series is the least-significant bit (LSB) or most-significant bit (MSB), you will end up padding the series differently:
v = [2 3 1 1 3 1 2 2]; % A sample 8-element vector
v = [v zeros(1,8)]; % If v(1) is the LSB, set the higher bits to zero
% or...
v = [zeros(1,8) v]; % If v(1) is the MSB, again set the higher bits to zero
If you want to process the entire vector all at once, here is how you would do it (with any necessary zero-padding included) for the case when vec(1) is the LSB:
nValues = numel(vec);
nRem = rem(nValues,16);
vec = [vec(:) zeros(1,nRem)]; % Pad with zeroes
vec = reshape(vec,16,[])'; % Reshape to an N-by-16 matrix
values = uint32(vec*4.^(0:15)');
and when vec(1) is the MSB:
nValues = numel(vec);
nRem = rem(nValues,16);
vec = [vec(1:(nValues-nRem)) zeros(1,nRem) ...
vec((nValues-nRem+1):nValues)]; % Pad with zeroes
vec = reshape(vec,16,[])'; % Reshape to an N-by-16 matrix
values = uint32(fliplr(vec)*4.^(0:15)');
I think you should have a look at bitget and bitshift. It should be possible to be something like this (pseudo-matlab code as I haven't worked with Matlab for a long time):
result = 0;
for i = 1:16 do
result += bitshift(bitget(vector(i), 2:-1:1), 2);
Note that this will give you the last bits of the first vector in the highest bits, so you might want to descend i from 16 to 1 instead