linux 如何提高给定随机函数的均匀分布?[关闭]

6xfqseft  于 12个月前  发布在  Linux
关注(0)|答案(3)|浏览(140)

已关闭。此问题需要更多focused。目前不接受回答。
**要改进此问题吗?**更新此问题,使其仅针对editing this post的一个问题。

两年前关闭。
Improve this question
这个问题与Linux上的Debian、bash和使用RANDOM的给定函数有关。
每一个改进都应该只使用bash。
给出了以下函数:

getRND(){
    min="${1:-1}"   ## min is the first parameter, or 1 if no parameter is given           
    max="${2:-100}" ## max is the second parameter, or 100 if no parameter is given
    rnd_count=$((RANDOM%(max-min+1)+min));
    echo "$rnd_count"
}

var=$(getRND -10 10) # Call the function
echo $var # output

字符串
如何也:

  • 提高随机性

该解决方案是为Linux系统寻找的,在这些系统上还没有安装bash 5.1,因此到目前为止还不能使用SRANDOM。

wrrgggsh

wrrgggsh1#

在给定的随机函数上有什么可以改进的,使它更随机,或者更大的范围,或者别的什么?
因此到目前为止还不能使用SRANDOM。
如果可能的话,如何提高上述函数的随机性?
Sooo用你自己的语义写你自己的SRANDOM。

srandom() {
   # take random number from /dev/urandom
   # we take only just 4 bytes - one 2^32 number
   printf "%d\n" "0x$(
       dd if=/dev/urandom of=/dev/stdout bs=4 count=1 status=none |
       xxd -p)"
}

字符串
然后:

normalize_value(){
   ...
   rnd=$(srandom)
   rnd_count=$((rnd / ...))
}


接受更大范围的数字
如果你对shell算法扩展的工作方式不满意,那么.使用不同的工具。bc计算器具有无限的范围。

rnd_count=$(echo "
     # see https://superuser.com/questions/31445/gnu-bc-modulo-with-scale-other-than-0
     scale=0; 
     # super big random number from three 2^32 numbers
     rnd = $(srandom) * 2^(32*2) +  $(srandom) * 2^32 + $(srandom)
     rnd % ($max - $min + 1) + $min
     " | bc)


你可以用getrandom()编写自己的C程序,并在运行时编译它,echo "int main() { stuff(); }" | gcc -xc - && ./a.out; rm ./a.out基本上可以为你提供任何你想要的语义。还有其他脚本语言,如perl,python,ruby,它们都有自己的大数字库和urandom数字生成实现。
每一个改进都应该只使用bash。
从我的Angular 来看是一个毫无意义的限制-总体而言,我支付的结果,不是真的“如何”我解决问题.无论如何,你可以,给你一堆想法如何进行:

  • 首先编写一个函数,从/dev/urandom读取字节并将其转换为数字。
  • 我不知道如何在纯bash中做到这一点,同时保持随机性在合理的水平。我怀疑输入会很快流失。
  • 你可以从urandom中读取一个字节。你必须忽略read的退出状态,因为这个字节可能是零字节或换行符。
  • 然后检查该字节是否为数字,如果不是,重复前面的步骤。
  • 把这样的算法当作0-9范围内的随机数的生成器。从这些数字中生成更大的数字。
  • 然后使用算术展开作为“后端”,用bash编写您自己的大数库。
  • 这似乎毫无意义,因为bc是普遍可用的。
  • 这将像通常的大型图书馆一样工作。
  • 我建议将数字存储为max 2^16的数字数组。为了获得灵感,研究用C和 C++ 编写的类似库,并将其转换为bash。
sgtfey8w

sgtfey8w2#

在主shell中为RANDOM创建种子并期望它在子shell中受到青睐是没有意义的,因为新shell会自己初始化种子。
因此,您需要播种并使用主shell的RANDOM,并将值传递到另一个函数中进行转换。
下面是一个如何让你种子工作的例子:

#!/bin/bash

normalize_value(){
    value_to_normalize=$1
    min="${2:-1}"   ## min is the first parameter, or 1 if no parameter is given           
    max="${3:-100}" ## max is the second parameter, or 100 if no parameter is given
    rnd_count=$((value_to_normalize % (max-min+1)+min));
    echo "$rnd_count"
}

RANDOM=$(date +%s%N | cut -b10-19)

rnd=$RANDOM # get random value in a context of main shell and your seed
var=$(normalize_value $rnd -10 10) # pass random value into normalizer function
echo $var # output

###### following example will NOT WORK because statement refers to subshell's random generator
RANDOM=1
var=$(normalize_value $RANDOM -10 10) # wrong random sequence is used (not seeded by you)
echo $var # output

var=$(normalize_value $RANDOM -10 10) # wrong
echo $var # output

字符串

oyxsuwqo

oyxsuwqo3#

这就是当问题中的代码和KamilCuk的答案中的代码组合在一个函数中时的样子,以便进行更均匀的随机分布:

#!/bin/bash

get_rnd_num_eq_dis(){
    min="${1:-1}"   # min is the first parameter, or 1 if no parameter is given           
    max="${2:-100}" # max is the second parameter, or 100 if no parameter is given
#   rnd=$(srandom)
    srnd="$((0x$(dd if=/dev/urandom of=/dev/stdout bs=4 count=1 status=none | xxd -p)))"
    rnd_count=$((srnd%(max-min+1)+min));
    echo "$rnd_count"
}

var=$(get_rnd_num_eq_dis -100 100) # Call the function
echo "$var" # output

sleep 2

字符串
备注:看起来可以使用的范围大于+-32000

相关问题