Fortran Coder

标题: 有没有简单方式实现类似python random.choice的方式,谢谢,谢谢 [打印本页]

作者: pazza    时间: 2021-1-11 22:16
标题: 有没有简单方式实现类似python random.choice的方式,谢谢,谢谢
随机抽取数组的元素,

随机数的办法在数组比较小的时候,总是有截断误差,没法均匀抽取



作者: 风平老涡    时间: 2021-1-12 03:26
参考 https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
作者: pazza    时间: 2021-1-12 10:33
风平老涡 发表于 2021-1-12 03:26
参考 https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

谢谢指点,

step1:生成从0到所剩元素个数之间的随机数k;
step2:将第 k 个数取出,并最后一个剩余元素与取出的元素交换,然后剩余元素的数量减一
step3:重复step1,step2,直至所有元素均取出
通过将取出元素与剩余的最后一个元素交换,总是可以保证生成随机数k所对应位置的元素时尚未取出的。同样可以保证元素的取出是服从均匀分布,且算法的时间复杂度为O(n)。

这个算法时间复杂度O(N),非常好

但是,以我有限的fortran知识,感觉只借助数组和指针的情况下,
还是没法解决我的问题。

step1:生成从0到所剩元素个数之间的随机数k;

这一步还是会碰到我的问题,实现不了N*random_num(x)刚好严格覆盖【1,N】







作者: pazza    时间: 2021-1-12 11:37
本帖最后由 pazza 于 2021-1-12 13:01 编辑
pazza 发表于 2021-1-12 10:33
谢谢指点,

step1:生成从0到所剩元素个数之间的随机数k;

生成pp的问题
[Fortran] 纯文本查看 复制代码
! ****************************************************************************************** !
Module random_choice_FYS
    use prec
    IMPLICIT NONE   


    Integer,allocatable,Target :: pos_tmp(:)
    Integer,Pointer :: posp(:)

    contains
!-------------------------------------------------------------------
!-------------------------------------------------------------------
Subroutine choice_FYS(NL,N,L,num,p,i,j)
    Integer,intent(IN) :: NL,N,L,num
    Integer,intent(INOUT) :: p
    Integer,intent(OUT) :: i,j
    Integer :: pp,tmp
    Real(kq) :: KK
!------------------------------------------------------------------


    call random_number(KK); pp=Int(KK*(NL-p-1) +1)

    if ((p < num))  Then
        p=p+1        
        i = int(pp/L)
        j = mod(pp,L)

        tmp = posp(NL-p+1)
        posp(NL-p+1) = posp(pp)
        posp(pp) = tmp
    else
        return
    endif
    !---------------------------
    Return
End subroutine choice_FYS
!-------------------------------------------------------------------
!-------------------------------------------------------------------
End Module random_choice_FYS
!***************************************************************************


作者: 布衣龙共    时间: 2021-1-12 14:59
本帖最后由 布衣龙共 于 2021-1-12 15:04 编辑

[Fortran] 纯文本查看 复制代码
Module random_choice_FYS
  implicit none
  integer,parameter,private :: kq = 4
contains

  Subroutine choice_FYS(x,y)
    Integer :: x(:)
    Integer,intent(INOUT) :: y(:)
    integer  :: m , p , j
    real(kq) :: KK
    m = size(x)
    Do j = 1 , size(y)
      call random_number(KK)
      p=Int(KK*M)+1
      if (p < m) x([p,m]) = x([m,p])
      y(j) = x(m)
      m = m - 1
    End Do
  End subroutine choice_FYS

End Module random_choice_FYS

Program Main
  use random_choice_FYS
  integer :: x(6) = [1,2,3,4,5,6]
  integer :: y(3)
  call random_seed()
  call choice_FYS(x,y)
  write(*,*) y
  write(*,*) x
End Program Main



作者: pazza    时间: 2021-1-12 19:13
布衣龙共 发表于 2021-1-12 14:59
[mw_shl_code=fortran,true]Module random_choice_FYS
  implicit none
  integer,parameter,private :: kq ...

学习了,非常感谢




欢迎光临 Fortran Coder (http://bbs.fcode.cn/) Powered by Discuz! X3.2