我正在编写一个子程序来反转矩阵。 输入是矩阵A(n乘n),输出是矩阵invA。在子例程中,我想声明一个临时矩阵“temp”维度(n乘2n),但声明引起了奇怪的问题。在这一行之后(我在下面强调),我也声明整数i和j并初始化它们i = 0,j = 0。 但调试i和j的这些值,它显示i = 1572472!奇怪的!!!!!如果我删除代码行“real,dimension(m,m * 2):: temp”那么一切都很好。谁能解释一下为什么?
提前谢谢。 (我是.Net中的优秀程序员,现在正在学习Fortran - 但它让我发疯了!)program weird
implicit none
Real, Dimension (2,2)::B
Real, Dimension (2,2) ::B_inversed
B(1,1) = 0.6
B(1,2) = 0.8
B(2,1) = -0.8
B(2,2) = 0.6
Call InverseMatrix(B,B_inversed)
contains
subroutine InverseMatrix(A, invA)
implicit none
real, intent(in), dimension (:,:) :: A
real, intent(out), dimension (size(a,1),size(a,2)) :: invA
real, dimension (size(a,1),2*size(a,2)) :: temp <------THIS LINE CAUSES PROBLEMS
integer:: i,j
i = 0 !<-------
j = 0 !<-------DEBUG line stops here, showing i = 3734648 !VERY WEIRD!!!!!
invA(1,1) =0.0
invA(1,2) =0.0
invA(2,1) =0.0
invA(2,2) =0.0
end subroutine
end program
这是一个非常直接的FORTRAN代码,但为什么我没有得到'i'的正确值?
答案 0 :(得分:3)
由于Fortran数组带有关于它们自己大小的信息,因此更好的方法是让你更像这样开始你的子程序:
subroutine inversematrix(a, inva)
! ALWAYS include the next line within any scoping unit
implicit none
real, intent(in), dimension (:,:) :: a ! no need to tell the compilers what the dims are
real, intent(out), dimension (size(a,1),size(a,2)) :: inva
real, dimension (size(a,1),2*size(a,2)) :: temp
要回答您的问题,我无法立即了解您的代码无效的原因以及为什么变量i
不会保留您为其分配的值。我想知道它是否连接到子程序的接口。在现代Fortran中,当技术上可行时,确保编译器生成必要的例程接口始终是一个好主意。实现这一目标的一种方法是将所有例程放入模块中,使用 - 关联它们,另一种方法是使用基本结构编写代码
program
! declarations
! executable statements
contains
subroutine ...
end subroutine
end program
而不是
subroutine ...
end subroutine
program
! declarations
! executable statements
end program
但我真的只是在猜测。
使用implicit none
并确保编译器生成例程接口;这些可能无法治愈你的直接问题,但它们是很好的一般指导方针,将来会为你节省很多痛苦。
答案 1 :(得分:0)
英特尔编译器在优化期间会做一些可能影响调试器输出的事情:
它会重新排列语句的顺序,因此分配j = 0的行可能会在指定i = 0的行之前运行。
它“优化”变量,不仅可以删除未使用的变量,还可以将变量与其他未同时使用的变量相结合。
这两个看起来都是不可预测的(至少对我而言)。因此,如果您已修复程序以使其具有正确的行为,并且打印该值会产生正确的答案,则调试器可能仍会显示错误的值。您可以尝试关闭/关闭优化,看看会发生什么。