Matlab имеет возможность иметь динамически типизированный массив.Например, код Matlab:
function testing1
clc;
close all;
chrom_len = 35;
function out = newChromosome(len)
genes_pool = struct(...
'gene', {'#', 'U-', 'Rs', '+', '-', '*', '/', '^'}, ...
'stackDepth', {0, 0, 1, 2, 2, 2, 2, 2},...
'deltaStack', {1, 1, 0, -1, -1, -1, -1, -1});
function gene = newGene(stackDepth)
% Select an appropriate gene
done = false;
while ~done
ind = randi([1 numel(genes_pool)], 1, 1);
if genes_pool(ind).stackDepth <= stackDepth
done = true;
end
end
% Generate output
gene = genes_pool(ind);
disp('start');
disp('gene.gene is ');
disp(gene.gene);
disp('stop');
if gene.gene == '#'
gene.gene = round(randn(1,1) * 5);
disp('new gene.gene is ');
disp(gene.gene);
disp('the gene is ');
disp(gene);
end
end
genes = {}; stack = [];
stackDepth = 0;
i = 1;
while i <= len || (i > len && stackDepth ~= 1)
gene = newGene(stackDepth);
% disp('outside gene');
% disp(gene);
class(gene.gene)
stackDepth = stackDepth + gene.deltaStack;
% disp('stackDepth');
% disp(stackDepth);
genes = [genes, gene.gene];
% disp('genes');
% disp(genes);
stack = [stack, stackDepth];
% disp('stack')
% disp(stack);
i = i + 1;
if strcmp(gene.gene, 'X') && rand(1,1) < 0.5
genes = [genes, randi([2 4], 1)]; stackDepth = stackDepth + 1;
stack = [stack, stackDepth];
genes = [genes, '^']; stackDepth = stackDepth - 1;
stack = [stack, stackDepth];
end
return;
end
out = struct('genes', {genes}, 'stack', {stack});
return;
end
newChromosome(2)
end
Выход Matlab при первом запуске (я использую GNU Octave, что то же самое):
start
gene.gene is
U-
stop
ans = char
Выход Matlab при втором запуске:
start
gene.gene is
#
stop
new gene.gene is
-11
the gene is
scalar structure containing the fields:
gene = -11
stackDepth = 0
deltaStack = 1
ans = double
Когда я переводю Matlab в Fortran, я хочу продублировать вывод, чтобы вывод Fortran был того же типа, что и в Matlab.Результаты gen.gene могут быть символьными или двойными.Это означает, что он может иметь два типа.Можно ли сделать то же самое в Фортране?Как мне динамически ввести переменную в Fortran?Я считаю, что это как-то связано с приведением типов.Пока что мое решение на Фортране таково:
function newchromosome(clen) result(out1)
implicit none
type garray
character*2 :: gene;
integer :: stackdepth;
integer :: deltastack;
end type
type(garray), dimension(8) :: genespool
type(garray), dimension(1) :: gene2
integer,intent(in) :: clen;
integer :: out1;
integer :: inttest;
genespool = [garray('#',0,1),garray('X',0,1),garray('U-',1,0), &
garray('+',2,-1),garray('-',2,-1),garray('*',2,-1), &
garray('/',2,-1),garray('^',2,-1) ]
gene2 = [garray('s',0,0) ]
out1 = clen;
inttest = newgene(2);
contains
function newgene(stackdepth) result(out2)
integer, intent(in) :: stackdepth;
integer :: out2;
logical :: done;
integer :: ind;
real :: rnd1;
character*2, dimension(:), allocatable:: answer2;
character*2 :: answer;
answer = 'ye'
out2=0;
allocate(answer2(1));
! gene=0;
! gene = stackdepth;
done = .FALSE.
do while (done .EQV. .FALSE.)
call random_number(rnd1);
ind = nint(rnd1*size(genespool));
if (genespool(ind)%stackdepth <= stackdepth) then
done = .True.
end if
end do
! Generate output
print*, "genespool(ind) ", genespool(ind);
print*, "gene 2 ", gene2;
gene2=genespool(ind)
print*, "new gene 2 ",gene2;
print*, "new gene2.gene ",gene2%gene;
answer2=gene2%gene;
print*, "test 2 ", answer;
if ( gene2(1)%gene == '#' ) then
call random_number(rnd1);
! gene2%gene = nint(rnd1*5); !<------ problem (convert integer to string integer)
endif
return;
end function newgene
end function newchromosome
program testing1
! ------ unit declaration ----------------------------------------------
use iso_fortran_env
implicit none
! ----------------------------------------------------------------------
! ------ variable declaration ------------------------------------------
integer :: chromlen;
integer :: newchromosome;
integer :: test;
chromlen = 35;
test = 0;
test=int(newChromosome(chromlen));
print*, "newChromosome is ", test;
flush( output_unit )
end program testing1
Я добавил несколько фиктивных переменных, таких как 'answer2', только для целей отладки.Я пометил стрелкой, где мой код в FORTRAN вызывает проблемы из-за объявления динамического типа Matlab.В Фортране может быть невозможно иметь переменную, которая является символьной и двойной (вещественной).В FORTRAN у меня не может быть U- и -11, как в Matlab, потому что в FORTRAN есть объявление типа gene2 как символа.Matlab гибок, FORTRAN строг.В FORTRAN, как я могу заставить gene2.gene принимать 'real type' -11, не вызывая ошибки?Есть ли лучший способ сделать объявление типа, например,% ptr или class (*) для объявления гетерогенного массива?