我正试图编写一个程序来查找整数数组的平均值、中值和模式,但在查找模式时遇到了一些复杂问题。以下是我迄今为止编写的代码。
首先,程序将提示用户输入将要输入的整数数的值,然后请求输入该整数数。然后按升序对整数进行排序,得到平均值和中值。
我遇到的问题是当我试图获得模式时。我能够计算重复值的出现次数。通过找到出现次数最多的值,我们将能够找到Mode。但我不确定该怎么做。Fortran中是否有任何内在函数来计算输入值的出现次数以及出现次数最多的值?
PROGRAM STATISTICS
!Created by : Rethnaraj Rambabu
IMPLICIT NONE
REAL, DIMENSION(:), ALLOCATABLE:: VAL
REAL TEMP, MEDIAN
REAL EVEN, MEAN, SUM, FMODE
INTEGER N, I,J
WRITE(*,*)' WHAT IS THE VALUE FOR N? '
READ(*,*) N
ALLOCATE(VAL(N))
WRITE(*,*) 'ENTER THE NUMBERS'
OPEN(1,FILE='FILE.TXT')
READ(1,*)(VAL(I),I=1,N)
CLOSE(1)
WRITE(*,*) VAL
!/---FOR SORTING----/!
DO I=1,N-1
DO J=1,N-1
IF(VAL(J) > VAL(J+1)) THEN
TEMP=VAL(J)
VAL(J)=VAL(J+1)
VAL(J+1)=TEMP
END IF
END DO
END DO
WRITE(*,*) VAL
!/-----MEDIAN----/!
IF ((N/2*2) /= N) THEN
MEDIAN=VAL((N+1)/2)
ELSE IF ((N/2*2) == N) THEN
EVEN= (VAL(N/2)+VAL((N+2)/2))
MEDIAN=EVEN/2
END IF
WRITE(*,*)'MEDIAN=', MEDIAN
!/----MEAN----/
SUM=0
DO I=1,N
SUM=SUM+VAL(I)
END DO
MEAN=SUM/N
WRITE(*,*)'MEAN=', MEAN
!/------MODE----/
FMODE=1
DO I=1,N-1
IF (VAL(I) == VAL(I+1)) THEN
FMODE=FMODE+1
END IF
END DO
WRITE(*,*)FMODE
END PROGRAM
FILE.TXT
包含
10 8 1 9 8 9 7 5 9 3 5 6
但是,如何做到这一点?或者Fortran中是否有任何内在函数来计算输入值的出现次数和出现次数最多的值。
不,没有。你必须手工计算模式。
以下代码应该可以工作(在排序数组上):
FMODE = VAL(1)
COUNT = 1
CURRENTCOUNT = 1
DO I = 2, N
! We are going through the loop looking for values == VAL(I-1)...
IF (VAL(I) == VAL(I-1)) THEN
! We spotted another VAL(I-1), so increment the count.
CURRENTCOUNT = CURRENTCOUNT + 1
ELSE
! There are no more VAL(I-1)
IF (CURRENTCOUNT > COUNT) THEN
! There were more elements of value VAL(I-1) than of value FMODE
COUNT = CURRENTCOUNT
FMODE = VAL(I-1)
END IF
! Next we are looking for values == VAL(I), so far we have spotted one...
CURRENTCOUNT = 1
END
END DO
IF (CURRENTCOUNT > COUNT) THEN
! This means there are more elements of value VAL(N) than of value FMODE.
FMODE = VAL(N)
END IF
说明:
我们在FMODE
变量中保持迄今为止的最佳模式,在COUNT
变量中保持FMODE
的计数。当我们逐步遍历数组时,我们在CURRENTCOUNT
变量中计算与我们现在看到的内容相等的命中数。
如果我们看到的下一项与上一项相等,我们只需增加CURRENTCOUNT
。如果不同,那么我们需要重置CURRENTCOUNT
,因为我们现在将计算下一个元素的重复次数。
在重置CURRENTCOUNT
之前,我们检查它是否大于以前的最佳结果,如果是,我们用新的最佳结果(无论在VAL(I)
和CURRENTCOUNT
处是什么)覆盖以前的最佳效果(FMODE
和COUNT
变量),然后继续。
这种重置不会发生在循环的末尾,所以我在末尾插入了另一个检查,以防最频繁的元素恰好是循环的最后一个元素。在这种情况下,我们会覆盖FMODE
,就像我们在循环中所做的那样。
这有点长,您可能会去掉可选参数,但这里提供了一个示例。他们使用这里实现的快速排序算法。
或者,您可以使用
integer function mode(arr) result(m)
implicit none
integer, dimension(:), intent(in) :: arr
! Local variables
integer, dimension(:), allocatable :: counts
integer :: i, astat
character(len=128) :: error_str
! Initialise array to count occurrences of each value.
allocate(counts(minval(arr):maxval(arr)), stat=astat, errmsg=error_str)
if (astat/=0) then
print'("Allocation of counts array failed.")'
print*, error_str
end if
counts = 0
! Loop over inputted array, counting occurrence of each value.
do i=1,size(arr)
counts(arr(i)) = counts(arr(i)) + 1
end do
! Finally, find the mode
m = minloc(abs(counts - maxval(counts)),1)
end function mode
这不需要任何排序。