You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否对以下Fortran彩票算法程序进行优化?

当然可以优化这段Fortran代码!我先梳理下原代码的核心逻辑——生成多组无重复的随机整数,然后从可读性、效率、健壮性几个维度来给出优化方案:

1. 优化变量命名,提升代码可读性

原代码的变量名(比如RAN4、N129)虽然能猜出大致用途,但更直观的命名能让代码更容易维护和理解。同时移除未使用的冗余变量:

program Lotto
    implicit none
    integer :: i, rand_idx
    integer, dimension(4) :: unique_4nums  ! 替代原RAN4
    integer, dimension(9) :: num_pool_9    ! 替代原N129(假设是1-9的候选池)
    integer, dimension(5) :: lotto_5nums   ! 替代原LOTTO5
    real :: r
    integer :: start_time, end_time, clock_rate  ! 补充完整计时变量(如果需要)

2. 用洗牌法替代循环重试,大幅提升生成无重复随机数的效率

原代码用DO...CYCLE的方式重复生成随机数直到得到不重复值,这种方法在候选范围小、要选的数量多的时候,重试概率会越来越高,效率很低。洗牌法是更高效的方案:先创建包含所有候选数的数组,打乱顺序后取前N个,一次就能得到无重复结果。

比如生成4个1-9的无重复数:

! 初始化候选池为1-9
num_pool_9 = [(i, i=1, 9)]

! 洗牌操作(Fisher-Yates算法)
do i = size(num_pool_9), 2, -1
    call random_number(r)
    rand_idx = 1 + int(i * r)  ! 生成1到当前i的随机索引
    ! 交换当前位置和随机位置的元素
    num_pool_9([i, rand_idx]) = num_pool_9([rand_idx, i])
end do

! 取前4个作为结果
unique_4nums = num_pool_9(1:4)

Fisher-Yates洗牌的时间复杂度是O(n),无论选多少个无重复数,效率都很稳定。

3. 优化随机数种子,提升随机性

原代码的call random_seed()默认初始化,部分编译器会使用固定种子,导致每次运行生成相同的随机序列。可以用系统时间来初始化种子,保证每次运行的随机性:

integer, dimension(:), allocatable :: seed
integer :: seed_size, seed_val

call random_seed(size=seed_size)
allocate(seed(seed_size))
! 用系统时钟生成初始种子
call system_clock(count=seed_val)
seed = seed_val + 37 * [(i-1, i=1, seed_size)]  ! 扩散种子值,避免全0
call random_seed(put=seed)
deallocate(seed)

4. 结构化代码,封装通用逻辑

把“生成无重复随机数”的逻辑封装成子过程,方便复用和维护:

subroutine gen_unique_randoms(pool_size, pick_count, result_arr)
    implicit none
    integer, intent(in) :: pool_size, pick_count
    integer, intent(out) :: result_arr(pick_count)
    integer :: i, rand_idx
    integer, dimension(pool_size) :: pool
    real :: r

    ! 初始化候选池
    pool = [(i, i=1, pool_size)]
    ! 洗牌
    do i = pool_size, 2, -1
        call random_number(r)
        rand_idx = 1 + int(i * r)
        pool([i, rand_idx]) = pool([rand_idx, i])
    end do
    ! 提取结果
    result_arr = pool(1:pick_count)
end subroutine gen_unique_randoms

主程序里直接调用即可:

call gen_unique_randoms(9, 4, unique_4nums)
call gen_unique_randoms(49, 5, lotto_5nums)  ! 假设乐透是从49个数里选5个,可按需调整

5. 补充计时逻辑(如果需要)

如果需要统计代码运行时间,可以用system_clock实现:

call system_clock(start_time, clock_rate)

! 这里放要计时的代码,比如生成随机数的逻辑
call gen_unique_randoms(9, 4, unique_4nums)
call gen_unique_randoms(49, 5, lotto_5nums)

call system_clock(end_time)
print *, "生成随机数耗时: ", real(end_time - start_time)/real(clock_rate), "秒"

优化后的完整代码示例

program Lotto
    implicit none
    integer :: start_time, end_time, clock_rate
    integer, dimension(4) :: unique_4nums
    integer, dimension(5) :: lotto_5nums

    ! 初始化随机数种子
    call init_random_seed()

    ! 计时开始
    call system_clock(start_time, clock_rate)

    ! 生成无重复随机数
    call gen_unique_randoms(9, 4, unique_4nums)
    call gen_unique_randoms(49, 5, lotto_5nums)

    ! 计时结束并输出
    call system_clock(end_time)
    print *, "4个1-9的无重复随机数: ", unique_4nums
    print *, "5个1-49的无重复随机数: ", lotto_5nums
    print *, "总耗时: ", real(end_time - start_time)/real(clock_rate), "秒"

contains

    subroutine init_random_seed()
        implicit none
        integer, dimension(:), allocatable :: seed
        integer :: seed_size, seed_val

        call random_seed(size=seed_size)
        allocate(seed(seed_size))
        call system_clock(count=seed_val)
        seed = seed_val + 37 * [(i-1, i=1, seed_size)]
        call random_seed(put=seed)
        deallocate(seed)
    end subroutine init_random_seed

    subroutine gen_unique_randoms(pool_size, pick_count, result_arr)
        implicit none
        integer, intent(in) :: pool_size, pick_count
        integer, intent(out) :: result_arr(pick_count)
        integer :: i, rand_idx
        integer, dimension(pool_size) :: pool
        real :: r

        pool = [(i, i=1, pool_size)]
        do i = pool_size, 2, -1
            call random_number(r)
            rand_idx = 1 + int(i * r)
            pool([i, rand_idx]) = pool([rand_idx, i])
        end do
        result_arr = pool(1:pick_count)
    end subroutine gen_unique_randoms

end program Lotto

内容的提问来源于stack exchange,提问作者F2HMcDonnell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:37:59