本地 Vim 随机数脚本

15

我知道有各种方法可以获取随机数,比如从shell中获取。但是,我在一台编译很少的安卓手机上运行vim。而且,它不必严格随机。问题是,在Vim中得到一系列相对较好的随机数的有趣、简洁、快速(即使用vim本地函数)和短的方法是什么?


关于vi.stackexchange.com上的此帖子 - jdhao
3个回答

19

尝试类似这样的代码

function Rand()
    return str2nr(matchstr(reltimestr(reltime()), '\v\.@<=\d+')[1:])
endfunction

我认为最好的选择是使用一些时间函数(有两个: reltime()localtime(),但后者只有每秒更新一次)。我宁愿避免使用随机数或者使用 pyeval('random.randint(1, 10)') (在该代码之前加上python import random),因为shell比较慢,并且我不信任基于时间的解决方案。

注意:文档说明了由reltime()返回的项的格式取决于系统,因此我使用reltimestr()而不是对类似于包含纳秒的reltime()[1]进行操作。


@Remonn由于任何基于时间的解决方案都将依赖于您的系统。在我的系统上,分布是均匀的: http://pastebin.com/gB1bvGw6。 - ZyX
@ZyX,我正在尝试在数据库中随机选择一个索引号以打乱多行的顺序。每个行号都在数据库中。你知道如何在vimscript中实现吗? - Reman
@ZyX,randomint是Python函数,对吧?我想在vimscript中实现它(我没有安装Python)。顺便说一句...我没有使用上面那段代码,而是用了这个:let newrandom = str2nr(matchstr(reltimestr(reltime()), '\d\d$'))(抱歉) - Reman
@Remonn 这是我用于测试的相同代码,可以从上面的链接中获取,尽管我没有过滤任何值。randint()和我的函数结果看起来很像,但这取决于系统。我没有更好的解决方案。请注意,如果没有Python,您将缺少一堆精彩的插件,例如powerline,并且在其他某些插件(例如我的aurum)中会出现性能下降或缺失功能。OP没有其他选择:在Android上没有带有+python的vim。 - ZyX
2
@Remonn,这个可以使用system()函数实现。 - ZyX
显示剩余5条评论

10

最近我也在 Vim script 中玩了一下随机数。以下是我在过程中找到的一些资源。

无需使用 Vim script

如果可以的话,请尽可能使用外部随机数生成器。通常来说,它们比 Vim script 实现更好、更快。

例如,尝试以下命令:

  • :python import random; print random.randrange(1, 7)
  • :echo system('echo $RANDOM')
  • 其他脚本语言,例如 Ruby

Vim script 库。这些库旨在提供高质量的 RNG 实现。

  • vital.vim 是由 vim-jp 用户组创建的优秀而全面的库。它们的随机数生成器具有令人印象深刻的功能,并且是我所知道的最好的纯 Vim script RNG。vital.vim 使用 Xorshift 算法。赶紧试试吧!

    使用 vital.vim 掷骰子:

    let Random = vital#of('vital').import('Random')
    echo Random.range(1, 7)
    
  • vim-rng是一个小型的随机数生成器插件。它导出了几个全局函数,这些函数依赖于multiply-with-carry算法。该项目似乎还在不断改进中。

    使用rng掷骰子:

  • echo RandomNumber(1, 6)
    
  • magnum.vim 是我自己编写的一个大整数库。最近,我添加了一个随机数生成器,可以生成任意大小的整数。它使用XORSHIFT-ADD算法

    使用magnum.vim掷骰子:

  • let six = magnum#Int(6)
    echo magnum#random#NextInt(six).Add(magnum#ONE).Number()
    
  • Rndm比其他库要早得多。它的功能通过一些全局函数暴露出来。使用Rndm掷骰子:

  • echo Urndm(1, 6)
    

讨论和片段

最后,一些有见地的讨论和Vim脚本片段的链接。

let g:rnd = localtime() % 0x10000

function! Random(n) abort
  let g:rnd = (g:rnd * 31421 + 6927) % 0x10000
  return g:rnd * a:n / 0x10000
endfunction
  • 另一个脚本,在一个名叫Bart的人的个人配置文件中找到。

  • Vimcasts.org的第57集介绍了Vim的“表达式寄存器”,并在整个过程中提到了随机数的示例。参考此Stackoverflow问题和ZyX的代码片段。推荐观看。

  • Vim维基上的Wikia有一篇“跳转到随机行”文章,其中包含一些尚未提到的资源。


  • 现在Another script的链接已经失效了。 - jdhao

    2
    根据他人的答案和来自互联网的其他资源,我编写了两个函数来生成给定范围[Low, High]内的随机整数。
    这两个函数都接受两个参数:LowHigh,并返回该范围内的随机数字。
    结合Python和Vim脚本的第一个函数。
    " generate a random integer from range [Low, High] using Python
    function! RandInt(Low, High) abort
    " if you use Python 3, the python block should start with `python3` instead of
    " `python`, see https://github.com/neovim/neovim/issues/9927
    python3 << EOF
    import vim
    import random
    
    # using vim.eval to import variable outside Python script to python
    idx = random.randint(int(vim.eval('a:Low')), int(vim.eval('a:High')))
    
    # using vim.command to export variable inside Python script to vim script so
    # we can return its value in vim script
    vim.command("let index = {}".format(idx))
    EOF
    
    return index
    endfunction
    

    纯Vim脚本

    我提出的第二个函数使用纯Vim脚本:

    function! RandInt(Low, High) abort
        let l:milisec = str2nr(matchstr(reltimestr(reltime()), '\v\.\zs\d+'))
        return l:milisec % (a:High - a:Low + 1) + a:Low
    endfunction
    

    使用luaeval()(仅适用于Neovim)

    生成随机数的第三种方法是通过luaeval()使用lua。

    注:该方法仅适用于Neovim。

    最初的回答。

    " math.randomseed() is need to make the random() function generate different numbers 
    " on each use. Otherwise, the first number it generate seems same all the time.
    luaeval('math.randomseed(os.time())')
    let num = luaeval('math.random(1, 10)')
    

    如果你想在非严肃的场合生成随机数,可以使用以下方法作为起点。

    原始答案翻译成中文为"最初的回答"。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接