Is there an equivalent MATLAB dec2bin function in Fortran? - matlab

I would like to find a similar function as dec2bin(d,n) in MATLAB, which produces a binary representation with at least n bits, for Fortran. Online I found this code, which converts decimal to binary but without a mechanism to decide the number of bits, and it asks for the user to decide whether its a positive integer or a positive real number...

Here is a solution based on the B edit operator (as per High Performance Mark's comment), that requires a fairly recent compiler.
!> Returns a binary representation of d as a string with at least n bits.
!> abs(d) < 2^52
function dec2bin(d, n)
implicit none
integer,intent(in) :: d
integer,intent(in),optional :: n
character(len=:),allocatable :: dec2bin
character(len=53) :: tmp
integer :: n_
character(len=8) :: f
if (present(n)) then
n_ = min(n, 53)
write(f,'(i2)') n_
f = '(B' // trim(adjustl(f)) // '.' // trim(adjustl(f)) // ')'
else
f = '(B53)'
endif
write(tmp,f) d
dec2bin = trim(adjustl(tmp))
end function
Note that this function does not check the sign (as the sign is correctly handled). If you want to limit this to positive integers, you need to do it outside the function.
Just because I had to look for the correct syntax myself, here are the relevant sections from the Fortran 2008 Standard, Cl. 10.7.2.4 "B, O, and Z editing":
1 The Bw , Bw .m, Ow , Ow .m, Zw , and Zw .m edit descriptors indicate that the field to be edited occupies w
positions, except when w is zero. When w is zero, the processor selects the field width. On input, w shall not be
zero. The corresponding input/output list item shall be of type integer, real, or complex.
[...]
6 The output field for the Bw .m, Ow .m, and Zw .m edit descriptor is the same as for the Bw, Ow, and Zw edit descriptor, except that the digit-string or hex-digit-string consists of at least m digits. If necessary, sufficient
leading zeros are included to achieve the minimum of m digits. The value of m shall not exceed the value of w ,
except when w is zero. [...]

Related

Matlab code to split a random data

In Matlab, how can I split a random data into two matrices, for example: X(i) is a random vector, where i=1:100, every data symbol is formed from four bits, where x(1) and x(2) are the MSB(Most Significant Bits), x(3) and x(4) are the LSB(Least Significant Bits). I want to split them to get a new matrices y1(for the MSB) and y2(for the LSB).
EDIT
Here is some example code but for some reason it does not seem to work,
M=16;
N=10;
c=randi([0 M-1],1,N);
xx=dec2bin(c);
for k = 1:N-1
for j= 1:4
y1(k)=xx(k);
y1(k+1)=xx(k+1);
y2(k+2)= xx(k+2);
y2(k+3)= xx(k+3);
end
end
The code you wrote seems to have some issues. I think some of the problems is based on a misunderstanding of matlab. I will write a short list of some issue here:
1) There is no string class in matlab. Instead there is char arrays. Further, Matlab does not use pointers or reference in the same ways as Java or c++. This means that you cannot have a vector with char arrays as you have there. This also mean y1 and y2 must be a matlab cell or a matrix to store the data.
2) If c is a vector, then xx will be a matrix and size(xx) == [length(c),dec2bin(max(x))] So to say, each string of binary values is a row and every row is exactly large enough for the the largest string to fit, eg.
a = [13,257];
b = dec2bin(a);
where b is a 2x9 matrix since b needs at least nine bits. So to your problem. I will vectorize the solution and also use the extra agument in dec2bin to lock the number of bits to 4. Try this,
function [msBit, lsBit] = test()
M=16;
N=10;
if M>16
error('M must not be greater than 4 bits');
end
c=randi([0 M-1],1,N);
xx = dec2bin(c,4);
disp xx
disp(xx)
disp ' '
% Take the 2 most significant bits from every row
msBit = xx(:,1:2);
% Take the 2 least significant bits from every row
lsBit = xx(:,3:4);
disp msb
disp(msBit);
disp ' '
disp lsb
disp(lsBit);
It is of course possible to work with int8 as well, then we need to use the bitwise operaton functions. This is more difficult and the result will of course be an int. So 1100 will be represented by 12. This does not seem to be what you are after though, so I will not do this here.
Hope it works and good luck!

MATLAB function that gives all the positive integers in a column vector

I need to create a function that has the input argument n, a integer , n>1 , and an output argument v, which is a column vector of length n containing all the positive integers smaller than or equal to n, arranged in such a way that no element of the vector equals its own index.
I know how to define the function
This is what I tried so far but it doesn't work
function[v]=int_col(n)
[1,n] = size(n);
k=1:n;
v=n(1:n);
v=k'
end
Let's take a look at what you have:
[1,n] = size(n);
This line doesn't make a lot of sense: n is an integer, which means that size(n) will give you [1,1], you don't need that. (Also an expression like [1,n] can't be on the left hand side of an assignment.) Drop that line. It's useless.
k=1:n;
That line is pretty good, k is now a row vector of size n containing the integers from 1 to n.
v=n(1:n);
Doesn't make sense. n isn't a vector (or you can say it's a 1x1 vector) either way, indexing into it (that's what the parentheses do) doesn't make sense. Drop that line too.
v=k'
That's also a nice line. It makes a column vector v out of your row vector k. The only thing that this doesn't satisfy is the "arranged in such a way that no element of the vector equals its own index" part, since right now every element equals its own index. So now you need to find a way to either shift those elements or shuffle them around in some way that satisfies this condition and you'd be done.
Let's give a working solution. You should really look into it and see how this thing works. It's important to solve the problem in smaller steps and to know what the code is doing.
function [v] = int_col(n)
if n <= 1
error('argument must be >1')
end
v = 1:n; % generate a row-vector of 1 to n
v = v'; % make it a column vector
v = circshift(v,1); % shift all elements by 1
end
This is the result:
>> int_col(5)
ans =
5
1
2
3
4
Instead of using circshift you can do the following as well:
v = [v(end);v(1:end-1)];

matlab functions about sine curve

I have a question about matlab programming about sine curve.
The question is as below:
Consider the definition: function [s1, s2, sums] = sines(pts,amp,f1,f2). The input, pts, is an integer, but amp, f1, and f2 and are not necessarily integers. Output argument s1 is a row vector whose length (number of elements) equals pts. The elements of s1 are the values of the sine function when it is given equally spaced arguments that start at zero and extend through f1 periods of the sine. (Note that we ask for full periods, so if f1 is an integer, both the first and the last element of s1 will be 0 other than a very small rounding error.) The amplitude of the sine wave equals amp. The vector s2 is the same as s1 except that s2 contains f2 periods. The vector sums is the sum of s1 and s2. If f2 is omitted, then it should be set to a value that is 5% greater than f1. If f1 is omitted also, then it should be set to 100. If amp is not provided, then it should default to 1. Finally, if pts is omitted as well, then it should be set to 1000.
Here is what I am confused: how to define step length pts. I used the following method but it fails to work. Please help me to fix it.
function [s1, s2, sums] = sines(pts,amp,f1,f2)
.................
t = linspace(0, 1, pts);
s1=amp*sin(2*pi*f1*t);
s2=amp*sin(2*pi*f2*t);
Thanks.
As far as the part of the code you are confused this should work for you:
n=pts-1
t=0:n;
s1=amp*sin(2*pi*f1/n*t);
s2=amp*sin(2*pi*f2/n*t);
then you sum s1+s2. You still need to handle the missing input if any.

Matlab log2 equivalent in fortran

I need to translate a code from matlab to fortran 90. What is the best way to implement an equivalent fortran code for the matlab log2 function that dissect floating-point numbers into exponent and mantissa. I need to compute E and F that are described in the matlab documentation :
"[F,E] = log2(X) returns arrays F and E. Argument F is an array of real values, usually in the range 0.5 <= abs(F) < 1. For real X, F satisfies the equation: X = F.*2.^E. Argument E is an array of integers that, for real X, satisfy the equation: X = F.*2.^E."
The Fortran standard has EXPONENT and FRACTION intrinsics that do this dissection. They are elemental, so if you pass them an array you get an array back.

Operations with large numbers

I have some numbers a_i (for i=1 to 10000).
I need to compute exp(a_i)/sum(exp(a_j)) using matlab.
Of course, it is impossible to calculate straight away. I found some tricks, the most interesting being:
"Suppose we want to find exp(7.0873e002). This will be a large number indeed but still just barely within matlab's capability of direct calculation. However, we can find the separate exponent and mantissa without calling on 'exp' as follows;
a = 7.0873e2;
x = a/log(10);
D = floor(x); % D will be an integer
F = 10^(x-D); % F will lie in 1 <= F < 10
Then D will be the power of ten and F the mantissa
F = 6.27376373225551 % The mantissa
D = 307 % The exponent (power of ten)
Compare that with the direct answer:
exp(a) = 6.273763732256170e+307"
I tried something similar, but the result in may case is Inf:
a = 7.0873e5;
x = a/log(10);
D = floor(x);
F = 10^(x-D);
exp(a) = Inf
Anyone has an idea?
Your answer is in F and D. Because your a is much larger than the example a (i.e. e5 vs e2) which they state is just barely within Matlab's range, yours must be well out of the range and thus becomes inf. But it doesn't matter because D and F hold your answer, you aren't supposed to be checkin g it against exp(a), the example only calculates exp(a) to demonstrate the proof of concept. But the whole point of this code is to give you a way to find exp of giant numbers.
In your case you get
D =
307797
and
F =
3.374110424643062 % Use format long
thus your answer is 3.374110424643062e+307797