I'm looking for a quick way to get a variat of dec2bin in Matlab such that it'll return a logical variable vector. For example given a number n=8 the output will be [1,0,0,0].
How can I do that?
The simplest way is to simply explode the binary representation returned by dec2bin (which is already a string!):
dec2bin(n) == '1'
For n = 8 this returns a logical vector
1 0 0 0
This will also work if n is a vector of numbers.
Since string '1' is char(49) and string '0' is char(48) you can use:
bin = dec2bin(dec) - 48;
This will output the result as an array of doubles, since you are performing an arithmetic operation over an array (the string coming from «dec2bin» is considered an array in Matlab)
If you want to convert very high integers to binary, I recommend using this code:
bin = mod(floor(dec.*2.^-(floor(log2(dec)):-1:0)),2);
In order to convert binary vector to decimal:
dec = sum(bin.*2.^((length(bin)-1):-1:0));
Don't use dec2bin, use bitget instead:
bitget(n, fix(log2(n)) + 1:-1:1)
P.S:
If you have an array of numbers and you want its binary representation as matrix of bits, you might want to take a look at this related question.
Example
n = 8
b = bitget(n, fix(log2(n)) + 1:-1:1)
This results in:
b =
1 0 0 0
Related
can I have something like
A=1:10;
A(1:2 && 5:6)=0;
meaning I want to zero out specific ranges within my vector index expression in one line
Is that possible?
And what if I wanted to zero out all the rest like
A(~[1:2]) = 0
What's the way of logical NOT within vector indexing?
Thanks
The following should work:
idx = [1:2,5:6];
A(idx) = 0
If you want to zero the complement of the vector of indices:
idx = [1:2,5:6];
A(~ismembc(1:length(A),idx)) = 0
Where ismembc is a faster, lightweight version of ismember that assumes the array is sorted and non-sparse with no NaN elements. (Credit goes to this question.)
Just do A([1:2 5:6]). I.e., just create a vector of the indices you want to zero out.
I have a matrix (n,16) filled with audio samples of 16 bits each.
So the matrix could look like:
[0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1; 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]
and so on. How can i actually play this as sound? sound() is using double floating points (from -1 to 1 values). If i could just convert it to those values, I guess it would work, but im not sure. Any suggestions?
#AnderBiguri pretty much nailed it. Take your array, convert it to signed double, normalize and play it.
As you have a n x 16 matrix, where each row is a sample and each column is a bit for that number, first we need to convert that matrix into double format. We can use bin2dec to help us to do that. However, bin2dec takes in a string. As such, we can convert our matrix into a string array like so. Let's assume that inSound contains your sound matrix that you specified before.
I will also assume that your bits are in Big-Endian format, so the most significant bit is the left most bit, following down to the right most bit.
According to your comments, the numbers are signed 1's compliment. This means that should the most significant bit be 1, we simply invert the entire number. As such, we can figure out which rows are negative by checking the entire first column to see if there is a 1 or 0. We find the rows with 1 and simply take 1 and subtract every single element in the array. As such:
checkSign = inSound(:,1) == 1;
inSound(checkSign,:) = 1 - inSound(checkSign,1);
Therefore, when we convert our number to decimal, we simply find those rows again that should be negative and simply negate them. Let's convert our numbers first.
inSoundString = char(inSound + '0');
char converts each number in a matrix or vector into its string representation, assuming that the input into char is an ASCII code. As such, when we add with 0, we are adding each number in inSound with the numerical ASCII code that is representative of what 0 is in ASCII. This is our baseline to start with. After that, inSound will add either 0 or 1 to this numerical code so that when we convert this whole matrix into a string, we will finally get the string representation of those numbers.
Now convert the binary strings into actual numbers:
outSoundDec = bin2dec(inSoundString);
This will take each row and convert it into its decimal equivalent. Now, if your bits are in Little-Endian, you can use swapbytes to flip the bits so that you can transform the bits to Big-Endian before proceeding. Now that we have converted our numbers, we need to negate those rows that were supposed to be negative.
As such:
outSoundDec(checkSign) = -outSoundDec(checkSign);
Now we need to normalize this so that the range is between -1 to 1. Given that you have specified that the range is between [-32768, 32767], we simply divide all of our numbers by 32768. Therefore:
outSound = outSoundDec / 32768;
The above code will now normalize your signal so that it goes from -1 to 1. You can use sound(outSound, Fs); to play your sound where Fs is the sampling frequency your signal was obtained at.
Good luck!
I have a large bit stream. (e.g. 10110001010101000.....001 size thousands or millions)
I want to assign this bit stream into a one column vector x.
x = zeros(n,1);
I have tried to use some mod or rem operations, there will have some problems.
I guess it caused by the integer size.
I want to ask is there any good method to solve this problem?
Thanks for reading.
Assuming, for example:
x = '10100101010101010100';
You could turn it into a logical column vector this way:
x = (x == '1')';
You can also use a simple subtraction trick with the ascii value of 0 -
x-'0'
Sample run -
>> x =
00101011001
>> x-'0'
ans =
0 0 1 0 1 0 1 1 0 0 1
Then, transpose the matrix to get a column vector - [x-'0']'.
Consider addressing the problem earlier in the processing, at load time. Each '0'/'1' character is stored as a byte, so load bytes (unsigned chars or uchar) which contain the character codes, then convert the character codes to the right 0/1 values:
fid = fopen('binchars.txt','r');
digits = fread(fid,'uchar') - 48
fclose(fid);
This is how I do it with arrays where binaries are stored
>> hhh=[1 0 1 0 1 0 0; 0 0 1 0 0 0 0; 1 0 1 0 0 0 0; 0 0 0 1 1 0 1]; find(hhh(:,1)==1)
ans =
1
3
and now I am trying to understand how to do it with binary numbers
>> hhhh=[1010100; 0010000; 1010000; 0001101]; find(hhhh(:,1)==1)
ans =
Empty matrix: 0-by-1
where the hack to break up all binaries back into arrays can work (ismember('101010','1') and then prepending with zeros) but I feel there is probably some better alternative so
By which command to check whether Nth bit active in binary number?
P.s. Harder puzzle: is there a type-agnostic solution that would work with both binaries and DEC?
String Input
If you have a string input, you can get away with testing for char equality:
find(hhh(:, 1) == '1')
for string arrays (i.e char matrices), you can extract both outputs of find (rows and columns) to be able to determine which active bit corresponds to which string:
[r, c] = find(hhh == '1');
Numeric Input
For numeric inputs, you can use bitget to get the binary representation. From there, it's very similar to the solution for string inputs:
B = bsxfun(#bitget, hhh, size(hhh, 1):-1:1);
[r, c] = find(B);
Note that find searches for non-zero elements, so there's no need to write find(B == 1) explicitly.
Combined Solution
If the solution for the "harder puzzle" is what you're after, you can determine the type of the input first, and handle it accordingly:
if ischar(hhh)
%// Apply solution to string array
%//...
else if isnumeric(hhh)
%// Apply solution to numeric input
%// ...
else
%// This type is unsupported
assert('Matrix is of unsupported type')
end
Repeating my comment in form of an answer:
There's no need to work with the string/array-like representation of the bits in this case.
You can use bitget right on the output of find(mlf). Like:
filled = find(mlf);
filled_and_bit2 = filled(logical(bitget(filled,2)));
You should store your binary number as a string matrix:
hhhh=['1010100'; '0010000'; '1010000'; '0001101'];
Then you can do
find(bin2dec(hhhh) >= bin2dec('1000000'))
returns:
ans =
1
3
or you could use the less intuitive (but probably faster)
find(hhhh(:,1)-'0') %// Or find(hhhh(:,1)=='1') as EitanT points out
to get the same result.
This is not a direct answer to the question but related -- good point by Sebastian in a comment! So suppose that the binaries are indices. Now instead of playing with dec2bin something like
>> hhh=dec2bin(find(mlf));B=bsxfun(#bitget, hhh, 8:-1:1);find(B)
Error using bsxfun
Non-singleton dimensions of the two input arrays must match each other.
we can directly address the indices like
>> filled = find(mlf);
filled_and_bit2 = bitget(filled,1);
filled(logical(filled_and_bit2))
ans =
1
7
where it finds the binaries with the first active bit.
Procedure
Data
>> mlf=sparse([],[],[],2^31,1);
mlf(1)=7;
mlf(4)=10;
mlf(7)=-1;
>> mlf
mlf =
(1,1) 7
(4,1) 10
(7,1) -1
>> find(mlf)
ans =
1
4
7
Interpret the index numbers as binary
(1,1) -----> 000001
(4,1) -----> 000100
(7,1) -----> 000111
Examples
Output 1: find cases where 3th bit is active
4
7
Output: find cases where 1st bit is active
1
7
Output: find cases where 2nd bit is active
4
So basically this is what I want to do:
I have the decimal value 3 as such:
x=3
Now i get the binary format as such:
s = dec2bin(x,3)
s = 011
The format of s is a string (correct?).
Now I would like to convert this value to a matrix, in order to do matrix operations on it. As such:
A = [0 1 1]
But I cannot seem to get this right. I have tried both str2mat and cell2mat but no results. Any ideas?
If you are 100% certain you will only be getting 0s and 1s, use:
a = '001';
b = double(a)-48;
(0 is 48 in ASCII)
Here's one way:
>> cellfun(#str2num, cellstr(s'))'
ans =
0 1 1
As you've noticed, MATLAB isn't that great for string manipulation. :)
You can as well do that:
x=3;
binNumber = dec2bin(x,3);
A=sprintf('%s',binNumber) - '0';