the conversion of decimal to binary of text derived from a file is
temp=textread('E:\one.txt', '%1s', 'whitespace', '');
text = char(temp);
y = zeros(length(text)*8,1);
for n = 1:1:length(text)
a=abs(text(n));
f = 8*(n-1)+1;
y(f:f+7,1)=(de2bi(a,8))';
end
disp('THE MAGNITUDE OF THE TEXT IS =');
disp(a);
disp(f);
x=y';
disp('THE BINARY BITS ARE');
disp(x);
output of this program if file contained '1' stored in it
THE MAGNITUDE OF THE TEXT IS =
49
1
THE BINARY BITS ARE
1 0 0 0 1 1 0 0
if the number of bit of x is 8bit then i want first 3 bits displayed in a variable and rest 5 bits in another variable
i want a program for this in matlab.
eg x=00110011
a=001
b=10011
encoding program
clc;
clear all;
temp=textread('E:\one.txt', '%1s', 'whitespace', '');
text = char(temp);
y = zeros(length(text)*8,1);
for n = 1:1:length(text)
a=abs(text(n));
f = 8*(n-1)+1;
y(f:f+7,1)=(de2bi(a,8))';
end
disp('THE MAGNITUDE OF THE TEXT IS =');
disp(a);
disp(f);
x=y';
disp('THE BINARY BITS ARE');
disp(x);
z=length(x);
savefile='D:\mat\z.mat';
save (savefile,'z','-MAT');
disp('TOTAL NUMBER OF BITS =');
disp(z);
bk=input('ENTER THE NUMBER OF ROWS =');
savefile='D:\mat\bk.mat';
save (savefile,'bk','-MAT');
c=z/bk;
savefile='D:\mat\c.mat';
save (savefile,'c','-MAT');
k=1;
for i=1:bk
for j=1:c
m(i,j)=x(k);
k=k+1;
end
end
%disp(m(i,j));
disp('THE MESSAGE BITS ARE ');
disp(m);
savefile='D:\mat\m.mat';
save (savefile,'m','-MAT');
m_tot=(size(m,1)*size(m,2));
savefile='D:\mat\m_tot.mat';
save (savefile,'m_tot','-MAT');
savefile='D:\mat\r1.mat';
r1=[randperm(bk),randperm(bk)];
save (savefile,'r1','-MAT');
disp(r1);
savefile='D:\mat\r2.mat';
r2=[randperm(bk),randperm(bk)];
save (savefile,'r2','-MAT');
disp(r2);
savefile='D:\mat\f(1).mat';
f1= randint(1,1,[1,bk]);
save (savefile,'f1','-MAT');
savefile='D:\mat\en.mat';
en(1,:)=m(f1,:);
save (savefile,'en','-MAT');
disp('DIRECTLY ASSIGNED BLOCK IS');
disp(f1);
for w=1:(length(r1))
en(w+1,:)=xor((m(r1(w),:)),(m(r2(w),:)));
disp('THE EXORED BLOCKS ARE= ');
disp(r1(w));
disp(r2(w));
end
disp('THE ENCODED BITS ARE');
disp(en);
en_tot=(size(en,1)*size(en,2));
disp('tot no of encoded bits');
disp(en_tot);
save (savefile,'en_tot','-MAT');
savefile='D:\mat\en_tot.mat';
the variable en should be split based on hop count same as u did with variable x.
Try this:
%After computing "x", the double array, as required...
d = input('Enter the length of the first sub-array: ');
a = x(1:d)
b = x(d+1:end)
For example:
>>
temp='1';
text = char(temp);
y = zeros(length(text)*8,1);
for n = 1:1:length(text)
a=abs(text(n));
f = 8*(n-1)+1;
y(f:f+7,1)=(de2bi(a,8))';
end
disp('THE MAGNITUDE OF THE TEXT IS =');
disp(a);
disp(f);
x=y';
disp('THE BINARY BITS ARE');
disp(x);
%After computing "x", the double array, as required...
d = input('Enter the length of the first sub-array: ');
a = x(1:d)
b = x(d+1:end)
The result would be:
THE MAGNITUDE OF THE TEXT IS =
49
1
THE BINARY BITS ARE
1 0 0 0 1 1 0 0
Enter the length of the first sub-array: 3
a =
1 0 0
b =
0 1 1 0 0
I'm still unsure as to what this program is supposed to achieve though.
EDIT
New code as per changed requirement:
>>
temp='1';
text = char(temp);
y = zeros(length(text)*8,1);
for n = 1:1:length(text)
a=abs(text(n));
f = 8*(n-1)+1;
y(f:f+7,1)=(de2bi(a,8))';
end
disp('THE MAGNITUDE OF THE TEXT IS =');
disp(a);
disp(f);
x=y';
disp('THE BINARY BITS ARE');
disp(x);
%After computing "x", the double array, as required...
d = input('Enter the hop-count vector: ');
for i=2:length(d)
d(i) = d(i) + d(i-1);
end
d = [0, ceil((d./d(end))*length(x))];
disp('The resultant split up is:')
for i=2:length(d)
disp(x((d(i-1)+1):d(i)));
end
The result will be:
THE MAGNITUDE OF THE TEXT IS =
49
1
THE BINARY BITS ARE
1 0 0 0 1 1 0 0
Enter the hop-count vector: [3 2 3]
The resultant split up is:
1 0 0
0 1
1 0 0
Just slice the array:
disp(x(1:3));
disp(x(4:end));
Related
As noted in this answer by Sam Roberts and this other answer by gnovice, MATLAB's colon operator (start:step:stop) creates a vector of values in a different way that linspace does. In particular, Sam Roberts states:
The colon operator adds increments to the starting point, and subtracts decrements from the end point to reach a middle point. In this way, it ensures that the output vector is as symmetric as possible.
However, offical documentation about this from The MathWorks has been deleted from their site.
If Sam's description is correct, wouldn't the errors in the step sizes be symmetric?
>> step = 1/3;
>> C = 0:step:5;
>> diff(C) - step
ans =
1.0e-15 *
Columns 1 through 10
0 0 0.0555 -0.0555 -0.0555 0.1665 -0.2776 0.6106 -0.2776 0.1665
Columns 11 through 15
0.1665 -0.2776 -0.2776 0.6106 -0.2776
Interesting things to note about the colon operator:
Its values depend on its length:
>> step = 1/3;
>> C = 0:step:5;
>> X = 0:step:3;
>> C(1:10) - X
ans =
1.0e-15 *
0 0 0 0 0 -0.2220 0 -0.4441 0.4441 0
It can generate repeated values if they are rounded:
>> E = 1-eps : eps/4 : 1+eps;
>> E-1
ans =
1.0e-15 *
-0.2220 -0.2220 -0.1110 0 0 0 0 0.2220 0.2220
There is a tolerance for the last value, if the step size creates a value just above the end, this end value is still used:
>> A = 0 : step : 5-2*eps(5)
A =
Columns 1 through 10
0 0.3333 0.6667 1.0000 1.3333 1.6667 2.0000 2.3333 2.6667 3.0000
Columns 11 through 16
3.3333 3.6667 4.0000 4.3333 4.6667 5.0000
>> A(end) == 5 - 2*eps(5)
ans =
logical
1
>> step*15 - 5
ans =
0
The deleted page referred to by Sam's answer is still archived by the Way Back Machine. Luckily, even the attached M-file colonop is there too. And it seems that this function still matches what MATLAB does (I'm on R2017a):
>> all(0:step:5 == colonop(0,step,5))
ans =
logical
1
>> all(-pi:pi/21:pi == colonop(-pi,pi/21,pi))
ans =
logical
1
I'll replicate here what the function does for the general case (there are some shortcuts for generating integer vectors and handling special cases). I'm replacing the function's variable names with more meaningful ones. The inputs are start, step and stop.
First it computes how many steps there are in between start and stop. If the last step exceeds stop by more than a tolerance, it is not taken:
n = round((stop-start)/step);
tol = 2.0*eps*max(abs(start),abs(stop));
sig = sign(step);
if sig*(start+n*step - stop) > tol
n = n - 1;
end
This explains the last observation mentioned in the question.
Next, it computes the value of the last element, and makes sure that it does not exceed the stop value, even if it allowed to go past it in the previous computation.
last = start + n*step;
if sig*(last-stop) > -tol
last = stop;
end
This is why the lasat value in the vector A in the question actually has the stop value as the last value.
Next, it computes the output array in two parts, as advertised: the left and right halves of the array are filled independently:
out = zeros(1,n+1);
k = 0:floor(n/2);
out(1+k) = start + k*step;
out(n+1-k) = last - k*step;
Note that they are not filled by incrementing, but by computing an integer array and multiplying it by the step size, just like linspace does. This exaplains the observation about array E in the question. The difference is that the right half of the array is filled by subtracting those values from the last value.
As a final step, for odd-sized arrays, the middle value is computed separately to ensure it lies exactly half-way the two end points:
if mod(n,2) == 0
out(n/2+1) = (start+last)/2;
end
The full function colonop is copied at the bottom.
Note that filling the left and right side of the array separately does not mean that the errors in step sizes should be perfectly symmetric. These errors are given by roundoff errors. But it does make a difference where the stop point is not reached exactly by the step size, as in the case of array A in the question. In this case, the slightly shorter step size is taken in the middle of the array, rather than at the end:
>> step=1/3;
>> A = 0 : step : 5-2*eps(5);
>> A/step-(0:15)
ans =
1.0e-14 *
Columns 1 through 10
0 0 0 0 0 0 0 -0.0888 -0.4441 -0.5329
Columns 11 through 16
-0.3553 -0.3553 -0.5329 -0.5329 -0.3553 -0.5329
But even in the case where the stop point is reached exactly, some additional error accumulates in the middle. Take for example the array C in the question. This error accumulation does not happen with linspace:
C = 0:1/3:5;
lims = eps(C);
subplot(2,1,1)
plot(diff(C)-1/3,'o-')
hold on
plot(lims,'k:')
plot(-lims,'k:')
plot([1,15],[0,0],'k:')
ylabel('error')
title('0:1/3:5')
L = linspace(0,5,16);
subplot(2,1,2)
plot(diff(L)-1/3,'x-')
hold on
plot(lims,'k:')
plot(-lims,'k:')
plot([1,15],[0,0],'k:')
title('linspace(0,5,16)')
ylabel('error')
colonop:
function out = colonop(start,step,stop)
% COLONOP Demonstrate how the built-in a:d:b is constructed.
%
% v = colonop(a,b) constructs v = a:1:b.
% v = colonop(a,d,b) constructs v = a:d:b.
%
% v = a:d:b is not constructed using repeated addition. If the
% textual representation of d in the source code cannot be
% exactly represented in binary floating point, then repeated
% addition will appear to have accumlated roundoff error. In
% some cases, d may be so small that the floating point number
% nearest a+d is actually a. Here are two imporant examples.
%
% v = 1-eps : eps/4 : 1+eps is the nine floating point numbers
% closest to v = 1 + (-4:1:4)*eps/4. Since the spacing of the
% floating point numbers between 1-eps and 1 is eps/2 and the
% spacing between 1 and 1+eps is eps,
% v = [1-eps 1-eps 1-eps/2 1 1 1 1 1+eps 1+eps].
%
% Even though 0.01 is not exactly represented in binary,
% v = -1 : 0.01 : 1 consists of 201 floating points numbers
% centered symmetrically about zero.
%
% Ideally, in exact arithmetic, for b > a and d > 0,
% v = a:d:b should be the vector of length n+1 generated by
% v = a + (0:n)*d where n = floor((b-a)/d).
% In floating point arithmetic, the delicate computatations
% are the value of n, the value of the right hand end point,
% c = a+n*d, and symmetry about the mid-point.
if nargin < 3
stop = step;
step = 1;
end
tol = 2.0*eps*max(abs(start),abs(stop));
sig = sign(step);
% Exceptional cases.
if ~isfinite(start) || ~isfinite(step) || ~isfinite(stop)
out = NaN;
return
elseif step == 0 || start < stop && step < 0 || stop < start && step > 0
% Result is empty.
out = zeros(1,0);
return
end
% n = number of intervals = length(v) - 1.
if start == floor(start) && step == 1
% Consecutive integers.
n = floor(stop) - start;
elseif start == floor(start) && step == floor(step)
% Integers with spacing > 1.
q = floor(start/step);
r = start - q*step;
n = floor((stop-r)/step) - q;
else
% General case.
n = round((stop-start)/step);
if sig*(start+n*step - stop) > tol
n = n - 1;
end
end
% last = right hand end point.
last = start + n*step;
if sig*(last-stop) > -tol
last = stop;
end
% out should be symmetric about the mid-point.
out = zeros(1,n+1);
k = 0:floor(n/2);
out(1+k) = start + k*step;
out(n+1-k) = last - k*step;
if mod(n,2) == 0
out(n/2+1) = (start+last)/2;
end
I have Matlab code for run length encoding and I want to make code for decoding. Please can anyone help me in making the decoder for this code?
The encoder is as the following:
function out = rle (image)
%
% RLE(IMAGE) produces a vector containing the run-length encoding of
% IMAGE, which should be a binary image. The image is set out as a long
% row, and the conde contains the number of zeros, followed by the number
% of ones, alternating.
%
% Example:
%
% rle([1 1 1 0 0;0 0 1 1 1;1 1 0 0 0])
%
% ans =
%
% 03453
%
level = graythresh(image);
BW = im2bw(image, level);
L = prod(size(BW));
im = reshape(BW.', 1, L);
x = 1;
out = [];
while L ~= 0,
temp = min(find(im == x));
if isempty(temp)
out = [out, L];
break;
end
out = [out, temp-1];
x = 1 - x;
im = im(temp : L);
L = L - temp + 1;
end
end
Matlab has a built-in function for run-length decoding, namely repelem (starting at R2015a). You feed it with a vector containing the original values (0 and 1 in your case) and a vector containing the run-lengths.
Let x = [0 3 4 5 3] be the input. Then,
y = repelem(mod(0:numel(x)-1, 2), x)
gives
y =
1 1 1 0 0 0 0 1 1 1 1 1 0 0 0
which is the orinal image in linearized form as per your encoding function.
There is also a shorter but more complex solution to this problem. You pass the gray value and rows of the gray level matrix to the function RLE and it gives you the answer.
function rle = RLE(gray_value, image_rows)
for i =1:image_rows
diF = diff([gray_value(i,1)-1, gray_value(i,:)]) ;
k = diff([find(diF), numel(gray_value(i,:))+1]);
rle=[gray_value(i,find(diF));k] ;
end
end
I have 30 .txt files with the same format as shown below. From each file, I need to extract the corresponding value and matrix, hence, I need to skip the string line and also void line. I also know the total count number for each n-by-n matrix for each time step (this case we have 5 5x5 matrix). However, my code does not work.
Here is the content of txt file
Current Time Step = 2
Array - one
1 2 3 4 5
2 0 1 0 0
3 1 0 0 0
4 0 0 0 1
5 0 0 1 0
Array - two
1 1 1 1 1
2 0 1 0 0
3 1 0 0 0
4 0 0 0 1
5 0 0 1 0
Array - three
1 0.000000000000000E+000 0.000000000000000E+000
2 -2.43840000000000 0.000000000000000E+000
3 2.43840000000000 0.000000000000000E+000
4 0.000000000000000E+000 -2.43840000000000
5 0.000000000000000E+000 2.43840000000000
Array - four
1 8.969565865552799E-004
2 3.871274684514957E-004
3 3.871274684514958E-004
4 3.871274684514958E-004
5 3.871274684514956E-004
Array - five
1 35472082.4364420
2 34502005.6533170
3 34502005.6533170
4 34502005.6533170
5 34502005.6533170
Time of Current Time Step = 0.537921191784371
Time at the End of Current Time Step = 0.559240045256864
Here is my code:
Nc = 5;
textFilename = ['TimeStep-2.txt'];
fid = fopen(textFilename);
for k = 1:1
zero = sscanf(fid,'%f','Delimiter','\n');
end
for k = (1+4):(1+(Nc-1)+4)
one = sscanf(fid,'%f %f %f %f %f',[5,inf]);
end
for k = (1+(Nc-1)+2*4):(1+2*(Nc-1)+2*4)
two = sscanf(fid,'%f %f %f %f %f',[5,inf]);
end
for k = (1+2*(Nc-1)+3*4):(1+3*(Nc-1)+3*4)
three = sscanf(fid,'%f %f %f',[3,inf]);
end
for k = (1+3*(Nc-1)+4*4):(1+4*(Nc-1)+4*4)
four = sscanf(fid,'%f %f',[2,inf]);
end
for k = (1+4*(Nc-1)+5*4):(1+5*(Nc-1)+5*4)
five = sscanf(fid,'%f %f',[2,inf]);
end
for k = (1+5*(Nc-1)+5*4+2):(1+5*(Nc-1)+5*4+2)
six = sscanf(fid,'%f','Delimiter','\n');
end
for k = (1+5*(Nc-1)+5*4+2*2):(1+5*(Nc-1)+5*4+2*2)
seven = sscanf(fid,'%f','Delimiter','\n');
end
fclose(fid);
I used fgetl to read single line at a time and then strtrim and strsplit to remove white spaces and split it. Lastly I converted into doubles:
% open text file
fid = fopen('data.txt');
% initialize struct
s = struct([]);
% initialize loop variables
incArrayIdx = false; % increment array index
arrayIdx = 1;
rowIdx = 1;
% read single line from file (removing '\n')
tline = fgetl(fid);
while ischar(tline) % while is not EOF
% trim white space at the beginning of line
tline = strtrim(tline);
% split lines into cells by spaces(default delimiter)
C = strsplit(tline);
% convert each cell from string to double
A = cellfun(#str2double,C);
if any(isnan(A)) % nans come from non-numeric data
rowIdx = 1; % reset row index
if incArrayIdx % if need to increase array index
arrayIdx = arrayIdx + 1;
incArrayIdx = false;
end
else % didn't find nans - only numeric data
% next time you find nan increase array index
incArrayIdx = true;
% set new row in array
s(arrayIdx).data(rowIdx,:) = A;
% increase row idx
rowIdx = rowIdx + 1;
end
% read next line
tline = fgetl(fid);
end
% close file
fclose(fid);
and you get:
{s.data}' =
5×1 cell array
[5×5 double]
[5×5 double]
[5×3 double]
[5×2 double]
[5×2 double]
By the way, it seems that your 3 last matrices are not 5x5, maybe this caused you the problems?
q = 2;
k= 2^q;
x1 = [0.0975000000000000, 0.980987500000000, -0.924672950312500, -0.710040130079246];
for i = 1 : length(x1)
[idx_centers,location] = kmeans(x1',q);
end
temp = idx_centers;
for i = 1 : length(x1)
if temp(i)== 2
idx_centers(i) = 0;
end
BinaryCode_KMeans(i) = idx_centers(i); % output is say [0,0,1,1];
end
strng = num2str(BinaryCode_KMeans);
DecX = bin2dec(strng);
In the above code snippet, I want to express the binary string to its decimal equivalent where the binary string is obtained from kmeans clustering. The decimal equivalent should either be 1,2,3, or 4 i.e., k = 2^q when q=2.
But sometimes after conversion, the decimal equivalent is 12 because for a 4 bit binary code we get decimal numbers in 1 to 16 or 0 -- 15. the number of elements in x1 can vary and can be less than or greater than k. What should I do so that I can always get the decimal equivalent of the binary code within k for any value of q?
First of, there is no need to run kmeans multiple times, it will calculate the cluster centers using a single run. Note that, the code below tries to find a mapping between the clustering results and n the number of samples. There are three ways in the code below to encode this information.
clear
clc
q = 2;
k= 2^q;
n = 4;
x1 = rand(n,1);
fprintf('x1 = [ '); fprintf('%d ', x1); fprintf(']\n');
[idx_centers, location] = kmeans(x1, q);
fprintf('idx_centers = [ '); fprintf('%d ', idx_centers); fprintf(']\n');
for i = 1:q
idx_centers(idx_centers == i) = i-1;
end
fprintf('idx_centers = [ '); fprintf('%d ', idx_centers); fprintf(']\n');
string = num2str(idx_centers');
% Original decimal value
DecX = bin2dec(string);
fprintf('0 to (2^n) - 1: %d\n', DecX);
% Reduced space decimal value
% Ignoring the 0/1 order as [ 1 1 0 0 ]
% would be the same as [ 0 0 1 1 ]
if DecX >= (2^n)/2
complement = bitget(bitcmp(int64(DecX)),n:-1:1);
DecX = bin2dec(num2str(complement));
end
fprintf('0 to ((2^n)/2) - 1: %d\n', DecX);
% Minimal Decimal value based on the number of samples
% in the 0's cluster which is in the range of 0 to n-1
fprintf('0 to n - 1: %d\n', numel(find(idx_centers == 0)));
Hint: If you change the q to more than 2, the code will not work because bin2dec only accepts zeros and ones. In case of having more than 2 clusters, you need to elaborate the code and use multidimensional arrays to store the pairwise clustering results.
I am trying to solve this problem:
Write a function called cancel_middle that takes A, an n-by-m
matrix, as an input where both n and m are odd numbers and k, a positive
odd integer that is smaller than both m and n (the function does not have to
check the input). The function returns the input matrix with its center k-by-k
matrix zeroed out.
Check out the following run:
>> cancel_middle(ones(5),3)
ans =
1 1 1 1 1
1 0 0 0 1
1 0 0 0 1
1 0 0 0 1
1 1 1 1 1
My code works only when k=3. How can I generalize it for all odd values of k? Here's what I have so far:
function test(n,m,k)
A = ones(n,m);
B = zeros(k);
A((end+1)/2,(end+1)/2)=B((end+1)/2,(end+1)/2);
A(((end+1)/2)-1,((end+1)/2)-1)= B(1,1);
A(((end+1)/2)-1,((end+1)/2))= B(1,2);
A(((end+1)/2)-1,((end+1)/2)+1)= B(1,3);
A(((end+1)/2),((end+1)/2)-1)= B(2,1);
A(((end+1)/2),((end+1)/2)+1)= B(2,3);
A(((end+1)/2)+1,((end+1)/2)-1)= B(3,1);
A(((end+1)/2)+1,((end+1)/2))= B(3,2);
A((end+1)/2+1,(end+1)/2+1)=B(3,3)
end
You can simplify your code. Please have a look at
Matrix Indexing in MATLAB. "one or both of the row and column subscripts can be vectors", i.e. you can define a submatrix. Then you simply need to do the indexing correct: as you have odd numbers just subtract m-k and n-k and you have the number of elements left from your old matrix A. If you divide it by 2 you get the padding on the left/right, top/bottom. And another +1/-1 because of Matlab indexing.
% Generate test data
n = 13;
m = 11;
A = reshape( 1:m*n, n, m )
k = 3;
% Do the calculations
start_row = (n-k)/2 + 1
start_col = (m-k)/2 + 1
A( start_row:start_row+k-1, start_col:start_col+k-1 ) = zeros( k )
function b = cancel_middle(a,k)
[n,m] = size(a);
start_row = (n-k)/2 + 1;
start_column = (m-k)/2 + 1;
end_row = (n-k)/2 + k;
end_column = (m-k)/2 + k;
a(start_row:end_row,start_column:end_column) = 0;
b = a;
end
I have made a function in an m file called cancel_middle and it basically converts the central k by k matrix as a zero matrix with the same dimensions i.e. k by k.
the rest of the matrix remains the same. It is a general function and you'll need to give 2 inputs i.e the matrix you want to convert and the order of submatrix, which is k.