V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ukipoi
V2EX  ›  程序员

请问下,比较简单的实现 0.5 到 2 之间的随机数的方法

  •  
  •   ukipoi · 2020-11-13 14:54:37 +08:00 · 7071 次点击
    这是一个创建于 1450 天前的主题,其中的信息可能已经有所发展或是发生改变。

    要求就是 扩大一倍或者缩小一倍,两边的概率相同。

    这个可以用 Math.radom(),仅以数学的方式,一行就完成吗?

    我好像只能先随机出是扩大还是缩小,然后在分别写扩大 /缩小的倍率。

    大大们可以给个其他的思路么?

    第 1 条附言  ·  2020-11-13 17:12:37 +08:00
    我觉得我的标题可能有误导。
    我的问题正确的描述应该是如下:
    “把一个数扩大或者缩小 N 倍,其中 1<N<=2 。扩大和缩小的概率应该相同”

    在数学上,把 X*N 其中 N 在 (1,2] 时符合扩大的描述,N 在 [0.5,1) 时符合缩小的描述
    103 条回复    2020-11-16 17:04:54 +08:00
    1  2  
    huijiewei
        1
    huijiewei  
       2020-11-13 14:56:36 +08:00
    不就是 50~200 之间 /100 就好了
    ukipoi
        2
    ukipoi  
    OP
       2020-11-13 14:58:44 +08:00
    @huijiewei
    这样 0.5-1 和 1-2 的概率不一样
    yukiww233
        3
    yukiww233  
       2020-11-13 15:00:42 +08:00
    没懂啥意思
    ran(1.5)+0.5?
    ukipoi
        4
    ukipoi  
    OP
       2020-11-13 15:02:05 +08:00
    @yukiww233
    这样子随机 0.5-1.5 全是扩大的
    只有 0-0.5 才是缩小的
    概率不一样吧?
    adajoy
        5
    adajoy  
       2020-11-13 15:02:57 +08:00
    (Math.random() * 3 + 1) / 2
    rioshikelong121
        6
    rioshikelong121  
       2020-11-13 15:04:39 +08:00
    Math.random() * 1.5 + 0.5 不行么。
    rioshikelong121
        7
    rioshikelong121  
       2020-11-13 15:05:35 +08:00
    @ukipoi 写几个测测简单跑跑几万次就知道了。验证成本又不高。
    nvkou
        8
    nvkou  
       2020-11-13 15:06:34 +08:00 via Android
    random 0.0 - 1 期望 0.5
    0.5—2 期望 1.25

    所以平移过去 random()+1.25 为啥不行?
    wysnylc
        9
    wysnylc  
       2020-11-13 15:06:39 +08:00
    随机数一律建议使用 ThreadLocalRandom
    kop1989
        10
    kop1989  
       2020-11-13 15:08:41 +08:00
    不太懂所谓“0.5-1 和 1-2 的概率不一样”是什么意思(概率论估计已经还给老师了😂)
    0.5~1 的跨度是 0.5,1~2 的跨度是 1,我的理解,如果是真随机,落在这两个域的概率必然不同……
    rioshikelong121
        11
    rioshikelong121  
       2020-11-13 15:10:46 +08:00
    真正有这种概率不均等的情况一般是用现成的 random API 求随机整数的时候。
    ukipoi
        12
    ukipoi  
    OP
       2020-11-13 15:12:06 +08:00
    @rioshikelong121
    嗯,应该是我想的有问题。
    下意识的以为 0.5-1.5 里包含的数比 0-0.5 包含的数多了
    ipwx
        13
    ipwx  
       2020-11-13 15:13:11 +08:00
    是说:

    1. 先投掷一枚硬币,决定是扩大或是缩小;
    2. 然后决定 1~2 之间的倍率?

    我的思路:

    u = random(-1, 1)

    if u < 0:
    ..x = x / (1 - u)
    else:
    ..x = x * (1 + u)
    xcstream
        14
    xcstream  
       2020-11-13 15:14:13 +08:00
    不知道题目表达的意思

    大概我想是 e 的 x 次方 在 0.5-2 之间 ,x 是平均分布
    ukipoi
        15
    ukipoi  
    OP
       2020-11-13 15:14:39 +08:00
    @rioshikelong121
    因为本来是 扩大或者缩小 1.1 1.2 1.3 - 2.0 倍
    请问 ((int)((Math.random()*3+1)*5)/10) 能不能满足要求呢?
    dobest
        16
    dobest  
       2020-11-13 15:15:17 +08:00
    如果要求 [0.5, 1] 和 [1, 2.0] 等概率的话,可以试试 v = math.random(); v + 0.5 if v <=0.5 else v*2; 但一行可能搞不定。其他 ax+b 的形式是线性变换可能无法做到直接变换成 [0.5, 1] 和 [1, 2.0] 是等概率的。
    misdake
        17
    misdake  
       2020-11-13 15:15:43 +08:00
    lz 的意思我觉得是先抛一个硬币决定乘和除,然后随机一个 1~2 之间的数字,用当前值乘或除(根据硬币)这个数。
    ukipoi
        18
    ukipoi  
    OP
       2020-11-13 15:16:18 +08:00
    @ukipoi
    应该是 ((int)((Math.random()*3+1)*5))/10
    ukipoi
        19
    ukipoi  
    OP
       2020-11-13 15:19:42 +08:00
    @ukipoi
    不对, (1-4)/2 的区间是 0.5-1.25 我被自己绕晕了 ;;
    ukipoi
        20
    ukipoi  
    OP
       2020-11-13 15:20:42 +08:00
    @ipwx
    我也是这个想法,但是不知道有没有其他解
    Xs0ul
        21
    Xs0ul  
       2020-11-13 15:34:04 +08:00 via Android
    因为概率密度不一样,是个分段函数,感觉上肯定是要用到 if else 。宁可多写几行,不然以后很容易被自己坑
    H15018327040
        22
    H15018327040  
       2020-11-13 15:35:43 +08:00
    Math.floor((Math.random()*1.5)+0.5),先随机一个 0 到 1.5 的数,然后再加上 0.5
    anzu
        23
    anzu  
       2020-11-13 15:35:58 +08:00   ❤️ 2
    Math.random 范围是 [0, 1),对其乘除改变区间长度,加减相当于数轴平移
    0.5~2 的区间长度 1.5,是原区间的 1.5 倍,所以 乘以 1.5
    新区间距数轴原点 0.5,所以 + 0.5
    因此结果是 Math.random() * 1.5 + 0.5
    任何区间都可以以此求解
    ukipoi
        24
    ukipoi  
    OP
       2020-11-13 15:44:49 +08:00
    @anzu
    但是原先 0-0.5 和 0.5-1 这两个区间的数是一样多的
    乘以 1.5 后 应当是 0-0.75 和 0.75-1.5 这两个区间的数是一样多的
    加上 0.5 后 应当是 0.5-1.25 和 1.25-2 这两个区间的数是一样多的
    我的要求是 0.5-1 和 1-2 这两个区间 数一样多
    nightwitch
        25
    nightwitch  
       2020-11-13 15:50:08 +08:00


    C++的标准库的实现,从[0,1)生成[a,b)之间的分布
    nightwitch
        26
    nightwitch  
       2020-11-13 15:52:22 +08:00
    @ukipoi 你#24 写的需求和题干的需求完全不一样啊。
    nightwitch
        27
    nightwitch  
       2020-11-13 15:55:09 +08:00
    你#24 的需求应该写成分段的形势,两个生成器,1 个生成[0.5,1) 一个[1,2), 然后用抛硬币的方式决定选用哪个生成器。
    ukipoi
        28
    ukipoi  
    OP
       2020-11-13 15:56:33 +08:00
    @nightwitch
    我应该是写了的 [要求就是 扩大一倍或者缩小一倍,两边的概率相同。] 可能表达的不太清楚
    vgbhne
        29
    vgbhne  
       2020-11-13 16:00:05 +08:00 via Android
    可以想成有两个面积相同的靶,用两次 ran 取其坐标看落在哪个靶上。
    Jooooooooo
        30
    Jooooooooo  
       2020-11-13 16:03:36 +08:00
    随机两次
    hitmanx
        31
    hitmanx  
       2020-11-13 16:07:50 +08:00
    r = rand() # 假设 rand()返回[0, 1]
    return (r + 0.5) if (r < 0.5) else r * 2 #相当于 50%的概率位于[0, 0.5),要把它 scale 到[0.5, 1); 50%的概率位于[0.5, 1],要把它 scale 到[1, 2]
    wlsnx
        32
    wlsnx  
       2020-11-13 16:08:39 +08:00
    你是不是想实现“使一个数乘以[0,2)中的一个随机数”? n*(random()*2),(random()*2) < 1 就是缩小,>1 就是放大,倍率也是随机的。( python 里 random()返回[0,1)中的一个随机浮点数,其他语言自行修改。)
    x4400177
        33
    x4400177  
       2020-11-13 16:14:24 +08:00
    @ukipoi 0.5-1 和 1-2 的概率本来就不一样
    hitmanx
        34
    hitmanx  
       2020-11-13 16:15:19 +08:00   ❤️ 1
    发完贴想起来,我这样写和你原帖是一样的,需要分情况讨论,原因是你这种表示方法(0.5 表示缩小一倍,2 表示放大一倍)不是对称也不是均匀分布的;另一个表示方法是负数表示缩小,正数表示放大,那么实际上就从[0.5,2]变成了[-2, 2],就对称了。

    因此换个思路的话,你这个其实是指数对称,也就是 2^-1 表示缩小一倍,2^1 表示放大一倍,这样指数项就变成了对称且均与分布的了:

    # 假设返回[-1, 1]
    return exp(2, rand())
    ifzzzh
        35
    ifzzzh  
       2020-11-13 16:17:35 +08:00
    生成-0.5~0.5,如果>0 就 x2,最后+1
    lsylsy2
        36
    lsylsy2  
       2020-11-13 16:20:16 +08:00   ❤️ 1
    x=(-1,1)之间随机数
    y=2^x ( 2 的 x 次方)
    这个 y 的分布不是线性平均的,但是可能是 LZ 需要的
    lsylsy2
        37
    lsylsy2  
       2020-11-13 16:21:32 +08:00
    Wincer
        38
    Wincer  
       2020-11-13 16:21:50 +08:00
    0-0.5,0.5-1,1-2,这几个区间的数的数量没办法比较大小,因为都是无穷多个数
    ifzzzh
        39
    ifzzzh  
       2020-11-13 16:24:33 +08:00
    建议先画出想要的概率密度函数
    ukipoi
        40
    ukipoi  
    OP
       2020-11-13 16:43:25 +08:00
    @x4400177
    问题是,我要扩大或者缩小 N 倍 ,其中 1<N<=2
    那在数学中的表述就是乘以一个 [0.5-2]的数值把。
    我认为扩大和缩小,应该是有一个概率是一样的。
    所以[0.5-1 )和( 1-2]也应该是一样的
    ukipoi
        41
    ukipoi  
    OP
       2020-11-13 16:44:32 +08:00
    @hitmanx
    谢谢解答
    wlsnx
        42
    wlsnx  
       2020-11-13 16:54:52 +08:00
    rand = random()
    if rand >= 0.5:
    return n * (rand * 2)
    else :
    return n * (rand + 0.5)
    是不是想要这个效果?
    ukipoi
        43
    ukipoi  
    OP
       2020-11-13 16:57:44 +08:00
    @wlsnx
    稍微有点不一样,else 后面是 return n*(rand*0.5+0.5)
    不过大致上这样实现的,我自己就是这样写的。
    我想问的其实是像 34 36 楼这样的解法
    reus
        44
    reus  
       2020-11-13 17:00:16 +08:00 via Android
    I =random()
    If i < 0.5 return i + 0.5
    Else return i * 2
    就是个分段函数啊,当然不可能一行公式表达出来
    ukipoi
        45
    ukipoi  
    OP
       2020-11-13 17:02:15 +08:00
    @ukipoi
    主要是思路明显就不一样
    我要的结果不一定是他们的结果
    我就想要一种新的思路
    “要扩大或者缩小 N 倍 ,其中 1<N<=2,那在数学中的表述就是乘以一个 [0.5-2]的数值把”
    我是这么理解的,既然[0.5-1)表示缩小,(1-2]表示扩大。他们在逻辑中没有问题,但是比较反常理。
    我就认为数学中一定有一个合理的解释,但是仅仅以无穷的数来解释我感觉很单调。
    那一定有一个让人一眼看到就很合理的解释
    ukipoi
        46
    ukipoi  
    OP
       2020-11-13 17:04:34 +08:00
    @reus
    我想问的其实不是说 把这个分段函数以一行公式表达出来。
    而是一个新的思路,向 45 楼我说的那样。
    感觉是我的标题误导了。我的问题其实是在第一行。
    lllllliu
        47
    lllllliu  
       2020-11-13 17:14:10 +08:00
    ..大数随机然后归一化哦。归一化之后哪个范围都是符合分布规律的呀。
    比如用高斯分布出的归一化随机数在转换扩大到哪个范围都是符合高斯分布到呀。
    lllllliu
        48
    lllllliu  
       2020-11-13 17:15:54 +08:00
    假设高斯分布得到到随机数是 0.5,那就是 min + 0.5 x (max-min) 比如 1-2 那就是 1.5 哦
    ukipoi
        49
    ukipoi  
    OP
       2020-11-13 17:18:00 +08:00
    @lllllliu
    因为计算机里不存在无穷大,所以我觉得不能直接的认为[0.5,1)和(1,2]里包含的数是相等的
    那就不能认为 random 出来的结果,[0.5,1)和(1,2]的概率是相等的
    lllllliu
        50
    lllllliu  
       2020-11-13 17:18:10 +08:00
    最简单的归一化 x = (x - min) / (max - min), 前端随机算法可以看你选择哦。输出的都是 0 ~ 1 直接的数,按照这个 min + 0.5 x (max-min) 怎么扩大都行。
    lllllliu
        51
    lllllliu  
       2020-11-13 17:19:01 +08:00
    @ukipoi 你的问题就是先选择一个符合你的随机数算法,进行归一化输出之后怎么扩大都是符合之前的随机数算法的
    ukipoi
        52
    ukipoi  
    OP
       2020-11-13 17:19:54 +08:00
    @ukipoi
    或许也可能计算机有 [0.5,1)和(1,2]的概率是相等 办法我不知道?
    lllllliu
        53
    lllllliu  
       2020-11-13 17:20:14 +08:00
    @ukipoi 你自己也知道计算机是有精度的,选择你觉得符合你想要的动态范围的数据类型去表示就可以了。
    oldw4ng
        54
    oldw4ng  
       2020-11-13 17:20:21 +08:00
    随机一个 1-2 的数然后再随机一个决定乘或除?
    lllllliu
        55
    lllllliu  
       2020-11-13 17:21:25 +08:00
    @ukipoi 相同的 bit 相同的算法出来的概率是相同的。不同的动态范围 那就存在压缩和扩展呢,就会出现你说的,永远不可能出现一些数。
    ukipoi
        56
    ukipoi  
    OP
       2020-11-13 17:22:58 +08:00
    @lllllliu
    对的对的,因为我的前提就是概率相等,应当从[0-0.5) 和 (0.5-1]推导到 [0.5-1]和[1-2]
    我这个算是弄反了?
    lllllliu
        57
    lllllliu  
       2020-11-13 17:23:07 +08:00   ❤️ 1
    @ukipoi 啦啦啦,所以有不同的归一化和标准化算法,题主可以研究下,俺们在研究很多东西的时候都会转换到 0 ~ 1 之间来解决的。
    xuanbg
        58
    xuanbg  
       2020-11-13 17:25:14 +08:00
    小数先定义精度吧,不定义精度的话,说啥都没意义。
    lllllliu
        59
    lllllliu  
       2020-11-13 17:32:33 +08:00
    总的来说感觉有点牛角尖了。
    假设精确到 1 位,也就是 0 ~ 1 之间有 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 这几个数。(动态范围)
    然后假设一个随机数算法输出 0.5 的几率是 50%。。
    那么扩大到 1-2 之间的话按照这个随机数算法出来 1.5 的几率也是 50%;
    所以。。。简单归一化(虽然多余) x = (x - min) / (max - min) = ( 0.5-0 ) / ( 1-0 ) = 0.5 (动态位置);
    然后。。1 + 0.5 x (2-1) = 0.5 (扩大后的位置);
    所以重心点应该在 随机数生成规则以及你需要的动态范围(精度,采样)这个在计算机里是有上限的。
    但是再怎么上限也不会影响随机算法的结果。。
    当您觉得精度不够可以升采样,当你觉得精度(动态过了)可以降采样。。
    啊啊啊随便扯的。。下班。
    0o0o0o0
        60
    0o0o0o0  
       2020-11-13 17:38:21 +08:00
    |random(0,2)-0.5|+0.5
    idlerlestat
        61
    idlerlestat  
       2020-11-13 17:43:53 +08:00
    这……不就是 2^randint([-1,1])吗,randint 表示从一个数组里随机取一个数
    wty
        62
    wty  
       2020-11-13 17:46:38 +08:00 via Android
    扩大和缩小比例本来就不均匀,感觉应该在对数上随机然后转换过来
    cigarzh
        63
    cigarzh  
       2020-11-13 17:49:47 +08:00
    先考虑精度+1

    这个不理清楚后面没法做
    xiaopang132
        64
    xiaopang132  
       2020-11-13 17:54:25 +08:00
    math.ramdom()*1.5 + 0.5
    0o0o0o0
        65
    0o0o0o0  
       2020-11-13 17:54:54 +08:00
    有个问题,“1/N 倍”概率如果要均匀分布,那肯定不是 if else 就能解决的
    reus
        66
    reus  
       2020-11-13 17:56:57 +08:00 via Android
    @ukipoi 你才明白啊?我给你的答案就是两条直线推出来的公式啊。0-0.5 是缩小,0.5 到 1 是放大,概率一样,再映射到 0.5-1 和 1-2,答案不就出来了
    设随机出来的是 x,要用的乘数是 y
    那就是
    Y =x + 0.5

    Y= 2x
    laqow
        67
    laqow  
       2020-11-13 17:57:54 +08:00 via Android
    没看懂,感觉应该从概率分布和概率分布的计算方面找答案。random 没记错就是 uniform 分布,根据自己需要把这个分布转换成其它分布就完了。
    CRVV
        68
    CRVV  
       2020-11-13 17:59:33 +08:00
    如果只考虑数学问题(不考虑什么浮点数运算的事情),也不考虑边界([] 和 () 的差别),这个问题是这样的

    已有一个 0-1 之间均匀分布的随机数 x,在上面加一个变换 f,变成 0.5-2 之间分布的随机数 y,要求 0.5-1 的概率和 1-2 的概率相等。问这个变换是什么。

    先假定 f 在 0.5-2 之间是单调连续函数(不单调的 f 当然也可以有,先不考虑了)

    那么,f(0.5) = 1 且 0.5 <= f(x) <= 2 的 f 都符合要求,比如 f(x) = x + 0.5

    如果再增加一个条件,y 在 0.5 - 2 的整个区间内的概率密度都不为 0
    那么只要 f(0) = 0.5, f(0.5) = 1, f(1) = 2,f 就满足要求,你随便假设比如 f(x) = ax^2 + bx + c 然后解 a b c 就好了。
    如果假设 f(x) = 2^(ax+b) ,就得到 lsylsy2 给出的指数函数。
    类似的还有很多符合条件的函数。

    如果再增加一个条件,0.5-1 和 1-2 之间的概率密度分别都是常数,那么两边都是直线。
    给定 f(0) = 0.5, f(0.5) = 1, f(1) = 2,结果是唯一的,就是那个分段函数。
    zhyl
        69
    zhyl  
       2020-11-13 18:03:32 +08:00
    分成两步:
    1. 一颗石子落在数轴(整个数轴 0.5 ~ 2 )上,落在 0.5 ~ 1 范围的概率 = 1 ~ 2 范围的概率
    2. 在落入的范围内取任意随机数,其概率都是相同的

    计算步骤:
    0. p = Math.random()
    1. p <= 2/3 则 (重置随机数种子后) Math.random()*0.5 + 0.5
    2. p > 2/3 则 (重置随机数种子后) Math.random()+1
    cmdOptionKana
        70
    cmdOptionKana  
       2020-11-13 18:27:44 +08:00
    随机数有两种:一种是 0-1 之间取随机数,有无限个;另一种是在有限的数量中(比如 5 号小球至 20 号小球,共 16 个小球中)随机选一个。

    区分这两种不同的方式来取随机数,就比较清晰了。
    cmdOptionKana
        71
    cmdOptionKana  
       2020-11-13 18:38:15 +08:00
    因此,如果楼主说的是 0.5 - 2 之间的 *无限个* 数字中取随机数,那么,这个问题本身就是错的。

    不存在这样的随机数,或者说这样设定范围必然会影响随机性。

    从无限个数字中取随机数,只能是在 0-1 之间取,或者 1-2 这样可以无损转换成 0-1 的范围中取。比如 1-3 就不行,2-4 就可以。
    cmdOptionKana
        72
    cmdOptionKana  
       2020-11-13 18:39:21 +08:00
    说错了,2-4 不行,2-3 可以,3-4 可以。
    xymn
        73
    xymn  
       2020-11-13 18:42:23 +08:00 via Android
    var rand = Math.random()
    if(rand<0.25){
    return r*8
    }else{
    return r*2
    }
    lancelock
        74
    lancelock  
       2020-11-13 19:19:42 +08:00 via iPhone
    随机范围 0-2,结果大于 1 直接乘,小于 1 的话先加 1 在反转作为分母,分子为 1,这个分数作为乘数
    wchyqqgmail
        75
    wchyqqgmail  
       2020-11-13 19:20:34 +08:00 via Android
    random(1,4)/2
    vgbhne
        76
    vgbhne  
       2020-11-13 20:30:25 +08:00 via Android
    计算机浮点数虽然可能精度上有差距,但是落在(-1,1 )以零为原点的个数是一样的。具体生成的数经过计算或许是错的,但是不影响两边的概率。具体和底层设计也相关。
    lance6716
        77
    lance6716  
       2020-11-13 20:47:47 +08:00 via Android
    充分证明程序员的数学基础有多差🤣
    yanqiyu
        78
    yanqiyu  
       2020-11-13 21:47:25 +08:00
    扩大和缩小概率一样?你可能希望无论是扩大还是缩小概率分布都均匀(生成一个线性变换),抑或是一边均匀另一边按照幂函数映射(你原先的做法就是 best practice ),或者两边都不一定均匀但是要满足幂函数变换下的不变( exp(2, rand()))。

    更一般的情况更为复杂(比如你需要指定某一侧具有复杂的概率密度函数形式)那就需要先计算出 pdf/cdf 做专门的生成器了( Inverse Transform Method )
    cnt2ex
        79
    cnt2ex  
       2020-11-13 23:57:04 +08:00   ❤️ 1
    (2 * Math.random()) % 1.5 + 0.5
    cnt2ex
        80
    cnt2ex  
       2020-11-14 00:04:51 +08:00
    ```
    import random

    run = 1000000

    first = 0
    second = 0

    for i in range(run):
    rnd = (2 * random.random()) % 1.5 + 0.5
    if rnd >= 0.5 and rnd < 1.:
    first += 1
    if rnd >= 1. and rnd < 2.:
    second += 1

    print(first / run, second / run, first + second == run)
    ```
    试着跑了一下,0.5 到 1 和 1 到 2 之间的概率差不多都是 0.5
    Lemeng
        81
    Lemeng  
       2020-11-14 00:14:45 +08:00
    都*10,就是 5-20 之间
    luwies
        82
    luwies  
       2020-11-14 00:22:45 +08:00
    1.5 * Math.radom() + 0.5
    Takuron
        83
    Takuron  
       2020-11-14 08:36:36 +08:00 via Android
    先不说怎么写,让你“缩小一倍”的老师一定语文有问题,记得清清楚楚这是高考病句类型的一种。
    chenyu8674
        84
    chenyu8674  
       2020-11-14 09:35:01 +08:00
    没有“缩小 N 倍”这种说法,应为为“变为 N 倍或变为 N 分之一”
    Anarchy
        85
    Anarchy  
       2020-11-14 10:31:48 +08:00 via Android
    所以楼主是希望生成一个 0.5-1 和 1-2 概率相同的么 79 楼的可以
    crackhopper
        86
    crackhopper  
       2020-11-14 10:46:31 +08:00
    一行代码? Math.pow(Math.random()+1, Math.pow(-1, (Math.random()>0.5)))
    crackhopper
        87
    crackhopper  
       2020-11-14 10:48:21 +08:00
    或者 (Math.random()>0.5) and Math.random()+1 or 1/(Math.random()+1)
    crackhopper
        88
    crackhopper  
       2020-11-14 10:48:37 +08:00
    或者 (Math.random()>0.5) and (Math.random()+1) or 1/(Math.random()+1)
    Delbert
        89
    Delbert  
       2020-11-14 12:57:38 +08:00
    @ukipoi 0.5-1 和 1-2 这两个区间 数都是无穷多,哪怕 0.5-0.5000001 数也是无穷多,不存在数字谁多谁少的问题。
    你的问题在与区间长度而不是数字数量。
    qaqLjj
        90
    qaqLjj  
       2020-11-14 13:27:54 +08:00
    ```javascript
    Math.pow(2,Math.random()*2 - 1)
    ```
    exiledkingcc
        91
    exiledkingcc  
       2020-11-14 15:43:07 +08:00
    你想要的是一个在 0.5-1 上是均匀分布,在 1-2 上也是均匀分布,但是落到 0.5-1 与 1-2 上的概率相等?
    这样的话,很多答案写的 2^(random() * 2 - 1)是不满足的。因为在这两个区间不是均匀分布的。
    其实很简单:abs(random() * 2 - 0.5) + 0.5
    PopRain
        92
    PopRain  
       2020-11-14 17:26:41 +08:00
    楼主数学水平不知道怎么样,语文水平我觉得有点堪忧。。。。看标题很简单,看说明、补充说明越看越看不懂到底要干什么
    dejavuwind
        93
    dejavuwind  
       2020-11-16 10:13:38 +08:00
    同 90L,缩小一倍为 2^-1,放大 1 倍为 2^1,其实就是放大的倍数均匀分布(-1,1 )
    ukipoi
        94
    ukipoi  
    OP
       2020-11-16 11:02:01 +08:00
    @exiledkingcc
    请教下,为什么是不满足的?
    2^(random() * 2 - 1) 这个函数图像时连续的,那应该是所有的 X 都有唯一对应的 Y,并且 所有确定的 X 都是 1/K 的概率(假设 K 是-1 到 1 的所有数的总量)。那所有的 Y 也是 1/K 的概率,[0.5,1)和(1,2]的概率也是一样,那范围内的所有数都在了
    abs(random() * 2 - 0.5) + 0.5 的话,有些 Y 对应了两个 X,这个意思是一样的么?
    ukipoi
        95
    ukipoi  
    OP
       2020-11-16 11:12:29 +08:00
    @CRVV
    请教下
    2^(random() * 2 - 1) 得到 0.5-0.75 的概率是比 0.75 到 1 的概率大。
    但是每一个 X 都只对应一个 Y,并且这个函数是连续的。
    那这个对应关系到底对不对呢?
    因为每一个 Y 出现的概率都是 1/K,这个是肯定的
    exiledkingcc
        96
    exiledkingcc  
       2020-11-16 11:18:55 +08:00
    @ukipoi
    2^(random() * 2 - 1)是指数分布啊,怎么可能和均匀分布是一样的???
    它取值在 0.5-1 与 1-2 上是等概率的。但是显然在 1-1.5 与 1.5-2 上不是的。其它等区间的概率也不是一样的。

    关键在于你想要的是一个什么样的概率分布。
    ukipoi
        97
    ukipoi  
    OP
       2020-11-16 11:25:56 +08:00
    @exiledkingcc
    但是每一个确定的 Y 出现的概率是一样的吧?
    CRVV
        98
    CRVV  
       2020-11-16 11:41:14 +08:00
    @ukipoi

    首先你需要说清楚你在讨论实数还是在讨论 64 位浮点数

    如果是实数,那么 “K 是-1 到 1 的所有数的总量” 这句话不成立,后面就不用讨论了。
    不能设 K 是无限,然后把 K 当一个有限的数来做后续的讨论。

    如果是 64 位浮点数,那么 “每一个 Y 出现的概率都是 1/K” 是错的。
    比如
    2 ^ 0.1000000000000002 和 2 ^ 0.10000000000000014 的结果都是 1.0717734625362934
    no1xsyzy
        99
    no1xsyzy  
       2020-11-16 11:53:17 +08:00
    你不规定随机分布函数?那不是就空气等于空气吗?
    @cmdOptionKana #71 无论实数还是有理数,0-1 和 0-2 是可以无损相互转换的……
    数学没有随机数,只有随机事件、概率分布、测度。
    CRVV
        100
    CRVV  
       2020-11-16 12:04:45 +08:00
    这里的关键是楼主没想清楚自己要的是什么

    给定的要求只有一个,>1 和 <1 的概率相等。
    这样不能确定唯一的答案,所以下面给出了很多不同的解答。
    给的解释又超出了楼主能解理的数学,所以估计现在更不懂了。

    除了上面那个给定的要求,显然还存在一个要求是概率在某种程度上是均匀的,但均匀又存在不同的均匀。

    比如把所有结果 round 到一个最接近的数,然后
    0.5 0.6 0.7 0.8 0.9 1.0 1.2 1.4 1.6 1.8 2.0 的概率相同
    1/2.0 1/1.8 1/1.6 1/1.4 1/1.2 1/1.0 1.2/1 1.4/1 1.6/1 1.8/1 2.0/1 的概率相同
    这两个也不一样,都可以被认为是均匀的

    上面说的,其实不仅 “每一个 Y 出现的概率都是 1/K” 对浮点数是错的,“所有确定的 X 都是 1/K 的概率” 也是错的。
    因为浮点数本身是不均匀的,但那个随机数是均匀的。

    建议楼主放弃这个问题吧,需要补的课挺多的。
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2785 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 13:25 · PVG 21:25 · LAX 06:25 · JFK 09:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.