Fortran Coder

查看: 77|回复: 5

[求助] 有没有简单方式实现类似python random.choice的方式,谢谢,谢谢

[复制链接]

6

帖子

2

主题

0

精华

入门

F 币
43 元
贡献
24 点
发表于 2021-1-11 22:16:06 | 显示全部楼层 |阅读模式
随机抽取数组的元素,

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


回复

使用道具 举报

80

帖子

2

主题

0

精华

大师

F 币
645 元
贡献
307 点

规矩勋章

发表于 2021-1-12 03:26:53 | 显示全部楼层

6

帖子

2

主题

0

精华

入门

F 币
43 元
贡献
24 点
 楼主| 发表于 2021-1-12 10:33:08 | 显示全部楼层
风平老涡 发表于 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】






6

帖子

2

主题

0

精华

入门

F 币
43 元
贡献
24 点
 楼主| 发表于 2021-1-12 11:37:12 | 显示全部楼层
本帖最后由 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
!***************************************************************************

7

帖子

0

主题

0

精华

专家

F 币
456 元
贡献
113 点

元老勋章

QQ
发表于 2021-1-12 14:59:27 | 显示全部楼层
本帖最后由 布衣龙共 于 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


6

帖子

2

主题

0

精华

入门

F 币
43 元
贡献
24 点
 楼主| 发表于 2021-1-12 19:13:34 | 显示全部楼层
布衣龙共 发表于 2021-1-12 14:59
[mw_shl_code=fortran,true]Module random_choice_FYS
  implicit none
  integer,parameter,private :: kq ...

学习了,非常感谢
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

QQ|捐赠本站|Archiver|关于我们 About Us|群聊|Fcode

GMT+8, 2021-1-25 01:52

Powered by Discuz! X3.2

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表