Fortran90中随机删除矩阵行触发SIGABRT错误,求解决方案
问题分析与解决方案
原代码的核心问题
- 数组越界触发崩溃:
你的h变量会在每次外层循环(a循环)中累加近1000次,第一次循环后h就会到999,远超NMatrix的729列上限,直接触发内存访问错误(也就是你看到的SIGABRT)。 - 逻辑混乱且效率极低:
每次“删除一行”都要复制整个矩阵,还会重复选中同一行删除(随机数可能重复),最终根本得不到729列的结果。 - 索引错误:
rand_num=int(rand_num*Mc)-1会生成-1到998的数,当rand_num=-1时,b /= -1永远成立,相当于没删任何行。
正确实现方式
直接生成不重复的随机索引,提取需要保留的列(或行,根据你的矩阵维度调整)是更高效且可靠的方案。下面用Fisher-Yates洗牌算法生成无重复的随机索引:
integer, parameter :: Mc=1000, N=729 real :: Matrix(3,Mc), NMatrix(3,N) integer :: indices(Mc), i, temp, rand_pos real :: rand_num ! 初始化索引数组为1到Mc的连续整数 do i=1, Mc indices(i) = i end do ! Fisher-Yates洗牌:打乱索引顺序,确保无重复 do i=Mc, 2, -1 call random_number(rand_num) rand_pos = int(rand_num * i) + 1 ! 生成1到i的随机整数 ! 交换当前位置与随机位置的索引 temp = indices(i) indices(i) = indices(rand_pos) indices(rand_pos) = temp end do ! 提取前N个打乱后的索引,复制到新矩阵 NMatrix(:,1:N) = Matrix(:,indices(1:N))
代码说明
- 先创建一个包含1到1000的索引数组,通过洗牌算法打乱顺序,确保每个索引只出现一次。
- 直接提取前729个索引对应的列,一次性完成复制,避免循环中的数组越界问题。
- 索引从1开始,符合Fortran的默认规则,不会出现负数索引的错误。
内容的提问来源于stack exchange,提问作者Marta
相关产品推荐
相关产品推荐

