簡體   English   中英

Fortran和Matlab混淆了if語句

[英]Fortran to Matlab confused to if statement

我必須將fortran程序轉換為matlab,我遇到了問題。 雖然當我運行matlab腳本時,fortran結果是正確的。 我認為問題出在第一個IF聲明中。 我錯過了matlab轉換的內容嗎? 提前致謝。

這是完整的程序,在Fortran和Matlab中都有結果。 最新版本是@Rotem的解決方案。 我也試圖將修復添加到f1和f2,因為@BenBarrowes提到但是程序再次陷入困境。 提前致謝 :)

Fortran版本

program asxm_2
implicit none
real(8) a,b, par1, sum,sum1,sum2, x,x1,x2, h, f,fa,fb,f1,f2,par2,e
integer n,j,y,k
real(8), allocatable, dimension (:) :: partitionS, valueS, errorS
a=0.
b=5.+85
par1=100*(atan(b)-atan(a)) 
fa=100/(1+a**2) 
fb=100/(1+b**2) 

print*, 'METHOD SIMPSON'
do n=1,1000000
    h=(b-a)/n
    sum1=0. 
    sum2=0. 
    x1=a 
    x2=a 
    do j=1,n-1 
        k=j 
        if(k/2/=j/2.) then 
            if(j==1) x1=x1+h 
            if(j>1) x1=x1+2*h 

            f1=100/(1+x1**2)
            sum1=sum1+f1
        else
            x2=x2+2*h 
            f2=100/(1+x2**2) 
            sum2=sum2+f2
        endif
    enddo
    par2= (h/3)*(fa+4*sum1+2*sum2+fb) 
    e=par1-par2
    if(abs(e)<=0.001) exit
enddo

y=n 
allocate(partitionS(y),valueS(y), errorS(y))
do n=1,y
     h=(b-a)/n
     sum1=0.
     sum2=0.
     x1=a
     x2=a
     do j=1,n-1
         k=j
         if(k/2==j/2.) then
             x2=x2+2*h
             f2=100/(1+x2**2)
             sum2=sum2+f2
         else
             if(j==1) x1=x1+h
             if(j>1) x1=x1+2*h
             f1=100/(1+x1**2)
             sum1=sum1+f1
         endif
     enddo
     partitionS(n)=n 
     valueS(n)= (h/3)*(fa+4*sum1+2*sum2+fb) 
     errorS(n)=par1-valueS(n)
 enddo
 print*, 'Below are the results'
 print*, partitionS(y), valueS(y), errorS(y)
 deallocate(partitionS, valueS, errorS)
 end

Fortran結果

Below are the results
332.00000000000000        155.96759681601489        9.7047371403391480E-004

Matlab版

a = 0;
b = 5.+85;
par1 = 100*(atan(b)-atan(a));
fa = 100/(1+a.^2);
fb = 100/(1+b.^2);

fprintf('METHOD SIMPSON\n');
for n = 1:1000000
    h=(b-a)/n;
    sum1=0;
    sum2=0;
    x1 = a;
    x2 = a;
    for j = 1:n-1
        k = j;
        if fix(k/2) ~= j/2 
            if j == 1
                x1 = x1+h;
            end
            if j > 1
                x1 = x1+2*h;
            end   
            f1 = 100/(1+x1.^2);
            sum1 = sum1 + f1;
        else
            x2 = x2+2*h;
            f2 = 100/(1+x2.^2);
            sum2 = sum2 + f2;
        end
    end
    par2 = (h/3)*(fa+4*sum1+2*sum2+fb);
    e = par1 - par2;
    if abs(e)<0.001
        break;
    end
end



y=n;
partitionS = zeros (n);
valueS= zeros (n);
errorS = zeros (n);


for n = 1:y
    h=(b-a)/n;
    sum1=0;
    sum2=0;
    x1=a;
    x2=a;
    for j = 1:n-1
        k = j;
        if fix(k/2) == j/2
            x2 = x2 + 2*h;
            f2 = 100/(1+x2.^2);
            sum2 = sum2 + f2;
        else
            if j == 1
                x1 = x1 + h;
            end
            if j > 1
                x1 = x1 + 2*h;
            end
            f1 = 100/(1+x2.^2);
            sum1 = sum1 + f1;
        end
    end
    partitionS(n) = n;
    valueS(n)= (h/3)*(fa+4*sum1+2*sum2+fb);
    errorS(n)=par1-valueS(n);
end

fprintf('Below are the results\n');
fprintf('%.25f\n',partitionS(n));
fprintf('%.25f\n',valueS(n));
fprintf('%.25f\n',errorS(n));

MATLAB結果

Below are the results
332.0000000000000000000000000
174.0415303853845900000000000
-18.0729630956556660000000000

就像francescalus評論的那樣,看起來問題與Fortran中的整數運算有關。

您可以在Matlab實現中修改第一個if語句,如下所示:

if fix(k/2) ~= j/2

在第二部分中,Matlab代碼中存在拼寫錯誤。
你寫了x2而不是x1

正確的代碼:

f1 = 100/(1+x1.^2); %Instead of f1 = 100/(1+x2.^2);

輕微缺陷:

if abs(e)<=0.001 %Instead of if abs(e)<0.001

我知道非常基本的Fortran,所以我並排執行了Matlab和Fortran代碼版本。
我使用調試器逐步執行代碼。
我使用了一些任意輸入值。

問題與第一個Fortran if語句有關: (k/2/=j/2.)
k是整數時, k/2評估為floor(k/2) ,並且j/2. 評估浮點(假設k為正)。
(我使用修復 Matlab函數,如果k也可以是負數)。

例:

integer j, k
j=3
k=3

print *, k/2
print *, j/2.
print *, k/2/=j/2.

結果:

           1
   1.500000
 T

在Matlab中,默認類型是double。

j=3;
k=3;

disp(k/2)
disp(j/2)
disp(k/2 ~= j/2)

結果:

1.5000

1.5000

 0

正如您所看到的,在Fortran條件中,計算結果為true ,而在Matlab中則為false


完整的Matlab代碼:

a = 0;
b = 5.+85;
par1 = 100*(atan(b)-atan(a));
fa = 100/(1+a.^2);
fb = 100/(1+b.^2);

fprintf('METHOD SIMPSON\n');
for n = 1:1000000
    h=(b-a)/n;
    sum1=0;
    sum2=0;
    x1 = a;
    x2 = a;
    for j = 1:n-1
        k = j;
        if fix(k/2) ~= j/2 
            if j == 1
                x1 = x1+h;
            end
            if j > 1
                x1 = x1+2*h;
            end   
            f1 = 100/(1+x1.^2);
            sum1 = sum1 + f1;
        else
            x2 = x2+2*h;
            f2 = 100/(1+x2.^2);
            sum2 = sum2 + f2;
        end
    end
    par2 = (h/3)*(fa+4*sum1+2*sum2+fb);
    e = par1 - par2;
    if abs(e)<=0.001
        break;
    end
end



y=n;
partitionS = zeros (n);
valueS= zeros (n);
errorS = zeros (n);


for n = 1:y
    h=(b-a)/n;
    sum1=0;
    sum2=0;
    x1=a;
    x2=a;
    for j = 1:n-1
        k = j;
        if fix(k/2) == j/2
            x2 = x2 + 2*h;
            f2 = 100/(1+x2.^2);
            sum2 = sum2 + f2;
        else
            if j == 1
                x1 = x1 + h;
            end
            if j > 1
                x1 = x1 + 2*h;
            end
            f1 = 100/(1+x1.^2);%f1 = 100/(1+x2.^2);
            sum1 = sum1 + f1;
        end
    end
    partitionS(n) = n;
    valueS(n)= (h/3)*(fa+4*sum1+2*sum2+fb);
    errorS(n)=par1-valueS(n);
end

fprintf('Below are the results\n');
fprintf('%.25f\n',partitionS(n));
fprintf('%.25f\n',valueS(n));
fprintf('%.25f\n',errorS(n));

Matlab輸出:

METHOD SIMPSON
Below are the results
332.0000000000000000000000000
155.9675968160148900000000000
0.0009704737140339148000000

我根據你的帖子做了一個小的fortran程序。 然后把它通過我的f2matlab fortran源碼到matlab源碼轉換器(matlab文件交換)。 這是fortran:

program kt_f
implicit none
integer j,n,k,f1,f2
real x1,x2,h,sum1,sum2

n=100
k=50

do j=1,n-1
 k=j
 if(k/2/=j/2.) then
  if(j==1) x1=x1+h
  if(j>1) x1=x1+2*h
  f1=100/(1+x1**2)
  sum1=sum1+f1
 else
  x2=x2+2*h
  f2=100/(1+x2**2)
  sum2=sum2+f2
 endif
enddo

print *,'sum1=',sum1
print *,'sum2=',sum2

end program kt_f

當我編譯並運行它時,輸出是:

sum1=   5000.000    
sum2=   4900.000 

這是matlab源碼的產生。 請注意,除了if語句中的fix之外,還需要在100 /行中進行另一個fix ,因為這也是一個整數除法。 這是matlab代碼:

function kt_f(varargin)
 clear global; clear functions;
 global GlobInArgs nargs
 GlobInArgs={mfilename,varargin{:}}; nargs=nargin+1;
 persistent f1 f2 h_fv j k n sum1 sum2 x1 x2 ; 

 if isempty(f1), f1=0; end;
 if isempty(f2), f2=0; end;
 if isempty(h_fv), h_fv=0; end;
 if isempty(j), j=0; end;
 if isempty(k), k=0; end;
 if isempty(n), n=0; end;
 if isempty(sum1), sum1=0; end;
 if isempty(sum2), sum2=0; end;
 if isempty(x1), x1=0; end;
 if isempty(x2), x2=0; end;

 n = 100;
 k = 50;

 for j = 1: n - 1;
  k = fix(j);
  if(fix(k./2) ~= (j./2.));
   if(j == 1);
    x1 = x1 + h_fv;
   end;
   if(j > 1);
    x1 = x1 + 2.*h_fv;
   end;
   f1 = fix(100./(1+x1.^2));
   sum1 = sum1 + f1;
  else;
   x2 = x2 + 2.*h_fv;
   f2 = fix(100./(1+x2.^2));
   sum2 = sum2 + f2;
  end;
 end;

'sum1=',sum1
'sum2=',sum2
end %program kt_f

這提供了與fortran相同的輸出。 請檢查並確定這是否解決了您的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM