Fortran 90-分段错误
我正在制作一个程序,将十进制整数转换为二进制表示形式。这是我的密码:Fortran 90-分段错误,fortran,fortran90,Fortran,Fortran90,我正在制作一个程序,将十进制整数转换为二进制表示形式。这是我的密码: program test implicit none integer, dimension(:), allocatable :: binary integer :: decimalnum, i, initvalue print*, "Enter decimal number to convert: " read*,initvalue decimalnum = initvalue i = 0 do while (decim
program test
implicit none
integer, dimension(:), allocatable :: binary
integer :: decimalnum, i, initvalue
print*, "Enter decimal number to convert: "
read*,initvalue
decimalnum = initvalue
i = 0
do while (decimalnum > 0)
if (MOD(decimalnum,2)==0) then
binary(i) = 0 ! this is as far as the program executes up to
decimalnum = decimalnum / 2
i = i + 1
else if (MOD(decimalnum,2)==1) then
binary(i) = 1
decimalnum = (decimalnum -1) / 2
i = i + 1
end if
end do
end program test
在标记点,它返回错误分段错误并以代码139退出
为什么会发生这种情况
提前感谢。根据评论,在定义二进制数组之前,您需要先执行一个allocate语句或其他为您进行分配的语句。最简单的分配语句形式类似于ALLOCATEbinary10,它将给定二进制数组10个元素,使用默认值,可以使用allocate语句起始数组索引1更改该数组 如果在使用阵列之前不容易知道分配的大小,则有两种基本方法: 执行两次传递,第一次传递只计算需要多少个元素,然后分配数组,第二次传递实际分配给相关元素。 将阵列分配到初始大小(可能为零),然后根据需要逐渐增大阵列。 与使用方法相关的决策有一些权衡,比如分配和计数时对每个测试的评估
在Fortran 90中,至少要转到Fortran 95!,增加一个可分配数组有点复杂分配一个临时数组,将数据从原始数组复制到临时数组,取消分配原始数组,将原始数组分配到新大小数组,将数据从临时数组复制回调整大小的原始数组,取消分配临时数组。在Fortran 2003中,此操作变得很简单。根据注释,在定义二进制数组之前,您需要先执行一条allocate语句或在后台为您执行分配的某些操作。最简单的分配语句形式类似于ALLOCATEbinary10,它将给定二进制数组10个元素,使用默认值,可以使用allocate语句起始数组索引1更改该数组 如果在使用阵列之前不容易知道分配的大小,则有两种基本方法: 执行两次传递,第一次传递只计算需要多少个元素,然后分配数组,第二次传递实际分配给相关元素。 将阵列分配到初始大小(可能为零),然后根据需要逐渐增大阵列。 与使用方法相关的决策有一些权衡,比如分配和计数时对每个测试的评估
在Fortran 90中,至少要转到Fortran 95!,增加一个可分配数组有点复杂分配一个临时数组,将数据从原始数组复制到临时数组,取消分配原始数组,将原始数组分配到新大小数组,将数据从临时数组复制回调整大小的原始数组,取消分配临时数组。在Fortran 2003中,这个操作变得很简单。所以这可能是一种糟糕的形式,当然是糟糕的运行时,它会复制数组的每一个位,但下面是我想到的。它似乎起作用了
program test
implicit none
integer, dimension(:), allocatable :: binary
integer :: decimalnum, i, initvalue, curSize, curBit
print*, "Enter decimal number to convert: "
read*,initvalue
decimalnum = initvalue
i = 1
ALLOCATE ( binary(1) )
curSize = 1
DO WHILE (decimalnum > 0)
IF (i > curSize ) THEN
curSize = curSize * 2
CALL expandArray( curSize, i-1 )
END IF
IF (MOD(decimalnum,2)==0) then
binary(i) = 0 ! this is as far as the program executes up to
decimalnum = decimalnum / 2
i = i + 1
ELSE IF (MOD(decimalnum,2)==1) then
binary(i) = 1
decimalnum = (decimalnum -1) / 2
i = i + 1
END IF
end do
PRINT*, binary
CONTAINS
SUBROUTINE expandArray( newSize, oldSize )
IMPLICIT NONE
INTEGER, DIMENSION(:), ALLOCATABLE :: temp
INTEGER :: j, newSize, oldSize
ALLOCATE( temp(newSize) )
DO j=1,oldSize
temp(j) = binary(j)
END DO
DEALLOCATE (binary)
ALLOCATE( binary(newSize) )
DO j=1,oldSize
binary(j) = temp(j)
END DO
DO j=oldSize+1,newSize
binary(j) = 0
END DO
DEALLOCATE (temp)
END SUBROUTINE
END PROGRAM test
所以这可能是一种糟糕的形式,当然是糟糕的运行时,它会复制数组中的每一位,但下面是我想到的。它似乎起作用了
program test
implicit none
integer, dimension(:), allocatable :: binary
integer :: decimalnum, i, initvalue, curSize, curBit
print*, "Enter decimal number to convert: "
read*,initvalue
decimalnum = initvalue
i = 1
ALLOCATE ( binary(1) )
curSize = 1
DO WHILE (decimalnum > 0)
IF (i > curSize ) THEN
curSize = curSize * 2
CALL expandArray( curSize, i-1 )
END IF
IF (MOD(decimalnum,2)==0) then
binary(i) = 0 ! this is as far as the program executes up to
decimalnum = decimalnum / 2
i = i + 1
ELSE IF (MOD(decimalnum,2)==1) then
binary(i) = 1
decimalnum = (decimalnum -1) / 2
i = i + 1
END IF
end do
PRINT*, binary
CONTAINS
SUBROUTINE expandArray( newSize, oldSize )
IMPLICIT NONE
INTEGER, DIMENSION(:), ALLOCATABLE :: temp
INTEGER :: j, newSize, oldSize
ALLOCATE( temp(newSize) )
DO j=1,oldSize
temp(j) = binary(j)
END DO
DEALLOCATE (binary)
ALLOCATE( binary(newSize) )
DO j=1,oldSize
binary(j) = temp(j)
END DO
DO j=oldSize+1,newSize
binary(j) = 0
END DO
DEALLOCATE (temp)
END SUBROUTINE
END PROGRAM test
下面是一种将整数i转换为二进制表示形式的简单方法:
write(*,'(b16)') i
如前所述,这不会写入任何前导0。如果你想要领先的0,试试看
当然,前面的代码将二进制表示写入默认输出单元,但使用Fortran的内部写入功能,我可以同样轻松地将位写入字符变量。例如:
character(len=16) :: bits
...
write(bits,'(b16.16)') i
将i的二进制数字写入字符变量位
现在,如果您真正想要的是创建一个整数数组,每个整数代表二进制表示的一位,那么
integer, dimension(16) :: bitarray
...
bitarray = 0
...
do ix = 1,len(bits)
if (bits(ix:ix)=='1') bitarray(ix) = 1
end do
可能会有用。这里有一个简单的方法将整数i转换为二进制表示:
write(*,'(b16)') i
如前所述,这不会写入任何前导0。如果你想要领先的0,试试看
当然,前面的代码将二进制表示写入默认输出单元,但使用Fortran的内部写入功能,我可以同样轻松地将位写入字符变量。例如:
character(len=16) :: bits
...
write(bits,'(b16.16)') i
将i的二进制数字写入字符变量位
现在,如果您真正想要的是创建一个整数数组,每个整数代表二进制表示的一位,那么
integer, dimension(16) :: bitarray
...
bitarray = 0
...
do ix = 1,len(bits)
if (bits(ix:ix)=='1') bitarray(ix) = 1
end do
可能会工作。1发生崩溃是因为您只为数组二进制文件分配了1个元素:,而While循环可能已移动到i=2,此时数组的索引超出了崩溃范围 Fortran有许多直接处理位的内在函数。比如说, Bit_Sizevar返回var中的位数,因此如果必须 如果是可分配的,现在您可以提前知道所需的数组大小 b BTestiVar,pos返回。为True。如果iVar中pos处的位为1 例如,使用上面的其他声明:
Integer :: n
n = Bit_Size(decimalnum)
If( Allocated(Binary) ) DeAllocate(Binary) ! good practice
Allocate( Binary(1:n) ) ! in general, should get IOStat, just in case
Binary(:) = 0
ForAll(i=1:n, Mask = BTest( decimalnum, i-1 ) ) ! remember, bit intrinsics index from 0
Binary(i) = 1
End ForAll
。。。与Do和While相比,这有点效率,并且可能有助于smp。Where/EndWhere构造也可以使用,但我发现ForAll的效率更高一些
c IBitsvar,pos,len从var中提取位,从pos开始计算len位数,例如,如果您想创建一个显式二进制表示,这可能是一种方法
等等
3如果你的意思是将十进制数转换为二进制数,那么你还有很多额外的问题,如果十进制数还包括浮点十进制数,即实数,因为实数的位表示是以指数表示的。我将假设情况并非如此,因为代码/解释要复杂得多
最后,在Fortran中,NUM通常是有符号NUM,前导位用于确定+ve 0或-ve 1。因此,如果您使用的是另一个方向Bin2Dec,那么您更希望使用一个额外的arg(可能是可选的)来控制结果是有符号的还是无符号的。如果是无符号的,则输出变量需要比输入变量更大。例如,如果将无符号1字节整数转换为Fortran整数,则必须至少使用2字节整数,即输入整数1必须输出为整数2等。1由于只为数组二进制分配了1个元素,因此会发生崩溃:,While循环可能已经转到i=2,此时数组的索引超出了范围 Fortran有许多直接处理位的内在函数。比如说, Bit_Sizevar返回var中的位数,因此如果必须使用可分配的,现在您可以提前知道所需的数组大小 b BTestiVar,pos返回。为True。如果iVar中pos处的位为1 例如,使用上面的其他声明:
Integer :: n
n = Bit_Size(decimalnum)
If( Allocated(Binary) ) DeAllocate(Binary) ! good practice
Allocate( Binary(1:n) ) ! in general, should get IOStat, just in case
Binary(:) = 0
ForAll(i=1:n, Mask = BTest( decimalnum, i-1 ) ) ! remember, bit intrinsics index from 0
Binary(i) = 1
End ForAll
。。。与Do和While相比,这有点效率,并且可能有助于smp。Where/EndWhere构造也可以使用,但我发现ForAll的效率更高一些
c IBitsvar,pos,len从var中提取位,从pos开始计算len位数,例如,如果您想创建一个显式二进制表示,这可能是一种方法
等等
3如果你的意思是将十进制数转换为二进制数,那么你还有很多额外的问题,如果十进制数还包括浮点十进制数,即实数,因为实数的位表示是以指数表示的。我将假设情况并非如此,因为代码/解释要复杂得多
最后,在Fortran中,NUM通常是有符号NUM,前导位用于确定+ve 0或-ve 1。因此,如果您使用的是另一个方向Bin2Dec,那么您更希望使用一个额外的arg(可能是可选的)来控制结果是有符号的还是无符号的。如果是无符号的,则输出变量需要比输入变量更大。例如,如果将无符号1字节整数转换为Fortran整数,则必须至少使用2字节整数,即输入整数1必须输出为整数2等。您有权进行调试吗?这样的gdbNo,我不知道如何使用。我对Fortran不太了解,但我只是查找了“Allocateable”,看起来您仍然需要一个“allocate”语句来实际保留空间。我将该行更改为allocatebinaryi=0,但编译器在allocate语句中返回语法错误。另外:数组以索引1开头。您有权访问调试吗?这样的gdbNo,我不知道如何使用。我对Fortran不太了解,但我只是查找了“allocatable”,看起来您仍然需要一个“allocate”语句来实际保留空间。我将该行更改为allocatebinaryi=0,但编译器在allocate语句中返回语法错误。另外:数组以索引1开头。注意:刚刚编辑-我错误地将binary作为expandArray的参数,而不是全局变量。出于某种原因,它还是起作用了。在任何情况下,它现在是固定的。我同意作者的观点,这段代码可能很糟糕,它会复制数组的每一位。它特别使用了FORTRAN77的continue语句,这些语句已被更好的功能所取代。@HighPerformanceMark尝试将其修饰得更好一点阵列重新分配,摆脱了do/continue。很明显,我还不是Fortran程序员,所以我非常感谢专业人士的编辑/反馈。注意:刚刚编辑-我错误地将二进制作为expandArray的参数,而不是全局变量。出于某种原因,它还是起作用了。在任何情况下,它现在是固定的。我同意作者的观点,这段代码可能很糟糕,它会复制数组的每一位。它特别使用了FORTRAN77的continue语句的功能,这些语句已被更好的功能所取代。@HighPerformanceMark尝试将其修饰得更好一点阵列重新分配,摆脱了do/contin
ue。很明显,我还不是Fortran程序员,所以我非常感谢专业人士的编辑/反馈。@AussieGamer:您将很难找到一个编译器,它可以接受2008年修订版添加的大量语法;现在市面上的大多数编译器都实现了Fortran 2003的大部分功能。@AussieGamer:你很难找到一个编译器,它能接受2008年修订版所增加的大部分语法;现在市场上的大多数编译器都实现了Fortran 2003的大部分功能。