明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 792|回复: 5

[讨论] 自己写了一个LISP的随机函数,但是结果不均匀分布,求大神给看看

[复制链接]
发表于 2016-10-24 10:58 | 显示全部楼层 |阅读模式
;;;随机函数
;;;参数是小数有效位数
;;;返回值[0,1)的左闭右开区间
(defun RANDOM        (x / tmp)
  (setq tmp (expt 10 x))
  (rtos (/ (rem (getvar "CPUTICKS") tmp) tmp) 2 x)
)
我是参照(defun ZL-RAND ()
  (/ (rem (getvar "CPUTICKS") 1984) 1983)
)这个函数写的,感觉这个函数的随机性比较小,实际他的结果取值只有1984个值吧?
;;;测试函数
(defun testnew(x / s0 s1 s2 s3 s4 s5 s6 s7 s8 s9)
(setq s0 0)
(setq s1 0)
(setq s2 0)
(setq s3 0)
(setq s4 0)
(setq s5 0)
(setq s6 0)
(setq s7 0)
(setq s8 0)
(setq s9 0)
(setq s0 0)
(repeat        x
  (cond
    ((= (BBRANDOM 1) "0.0") (setq s0 (1+ s0)))
    ((= (BBRANDOM 1) "0.1") (setq s1 (1+ s1)))
    ((= (BBRANDOM 1) "0.2") (setq s2 (1+ s2)))
    ((= (BBRANDOM 1) "0.3") (setq s3 (1+ s3)))
    ((= (BBRANDOM 1) "0.4") (setq s4 (1+ s4)))
    ((= (BBRANDOM 1) "0.5") (setq s5 (1+ s5)))
    ((= (BBRANDOM 1) "0.6") (setq s6 (1+ s6)))
    ((= (BBRANDOM 1) "0.7") (setq s7 (1+ s7)))
    ((= (BBRANDOM 1) "0.8") (setq s8 (1+ s8)))
    ((= (BBRANDOM 1) "0.9") (setq s9 (1+ s9)))
  )
)
(princ "\n")
(princ s0)
(princ " ")
(princ s1)
(princ " ")
(princ s2)
(princ " ")
(princ s3)
(princ " ")
(princ s4)
(princ " ")
(princ s5)
(princ " ")
(princ s6)
(princ " ")
(princ s7)
(princ " ")
(princ s8)
(princ " ")
(princ s9)
(princ " ")
(princ "\n")
  )
下面测试了3组,每组3次,前2组是在同一台笔记本上,后一组是在台式机上
;;;测试(RANDOM 1)
;;;testnew10000
;;;808 1104 734 818 556 701 453 531 367 449
;;;869 1091 689 862 550 645 445 490 379 475
;;;868 1049 735 824 597 658 470 514 378 436
;;;testnew100000
;;;8735 10371 6958 8427 5603 6753 4550 5522 3764 4438
;;;8490 10500 6846 8427 5731 6833 4683 5591 3667 4582
;;;8504 10455 6890 8510 5577 6669 4521 5540 3756 4553
;;;testnew100000
;;;6738 9332 9137 8376 8310 6096 5438 3038 5058 4209
;;;6749 9378 9324 7650 8226 6445 5547 2922 5023 4384
;;;6892 8777 9524 7825 7694 6162 5937 3149 5132 4151
为啥不是均匀分布的呢?

发表于 2016-10-24 11:15 | 显示全部楼层

  1. (defun RAND () (/ (rem (getvar "CPUTICKS") 2016) 2015))
  2. (defun c:tt () (repeat 20 (princ "\n") (princ (RAND))))
发表于 2016-10-24 11:17 | 显示全部楼层
均匀就不叫随机了。
 楼主| 发表于 2016-10-24 12:00 | 显示全部楼层
貌似上一个测试函数有问题,改了一下
;;;测试函数
(defun testnew(x / tmp s0 s1 s2 s3 s4 s5 s6 s7 s8 s9)
(setq s0 0)
(setq s1 0)
(setq s2 0)
(setq s3 0)
(setq s4 0)
(setq s5 0)
(setq s6 0)
(setq s7 0)
(setq s8 0)
(setq s9 0)
(setq s0 0)
(repeat        x
  (setq tmp (BBRANDOM 1))
  (cond
    ((= tmp "0.0") (setq s0 (1+ s0)))
    ((= tmp "0.1") (setq s1 (1+ s1)))
    ((= tmp "0.2") (setq s2 (1+ s2)))
    ((= tmp "0.3") (setq s3 (1+ s3)))
    ((= tmp "0.4") (setq s4 (1+ s4)))
    ((= tmp "0.5") (setq s5 (1+ s5)))
    ((= tmp "0.6") (setq s6 (1+ s6)))
    ((= tmp "0.7") (setq s7 (1+ s7)))
    ((= tmp "0.8") (setq s8 (1+ s8)))
    ((= tmp "0.9") (setq s9 (1+ s9)))
  )
)
(princ "\n")
(princ s0)
(princ " ")
(princ s1)
(princ " ")
(princ s2)
(princ " ")
(princ s3)
(princ " ")
(princ s4)
(princ " ")
(princ s5)
(princ " ")
(princ s6)
(princ " ")
(princ s7)
(princ " ")
(princ s8)
(princ " ")
(princ s9)
(princ " ")
(princ "\n")
  )
testnew10000:
1902 10256 12554 11471 13948 10919 12431 647 12934 12938
1942 10759 12203 12095 12056 11787 12260 1745 12013 13140
1920 10951 13043 10768 13998 10926 12995 142 13413 11844
1539 10907 12577 12029 12258 12044 12675 1165 12362 12444
1149 11255 12116 12281 12874 11794 12189 977 12074 13291
4902 10407 10770 9761 14589 11160 10253 3965 10665 13528
3688 9913 12143 10861 12486 11208 11999 2928 12410 12364
2748 10365 12590 11046 13110 11241 12322 1565 12725 12288
2228 10314 12148 11691 12732 11592 12485 1624 12449 12737
1523 10799 12371 11640 13473 11541 12367 748 12713 12825
这回更不均匀了。。 0 和7 的概率差了数量级了。。
谢谢  xyp1964  自贡黄明儒  的回复
xyp1964  发的函数跟我参考的那个差不多 我就是觉得这样的函数出来的数值只有有限(2016)的个数
可能有些时候做一些模拟统计的话会出偏差
自贡黄明儒  说均匀就不叫随机了貌似有点极端了吧。。。随机数还是应该均匀些吧?各种编程语言的伪随机数貌似是均匀分布的
发表于 2016-10-24 13:06 | 显示全部楼层
本帖最后由 自贡黄明儒 于 2016-10-24 13:09 编辑
downhh 发表于 2016-10-24 12:00
貌似上一个测试函数有问题,改了一下
;;;测试函数
(defun testnew(x / tmp s0 s1 s2 s3 s4 s5 s6 s7 s8 s ...

那你试一下高飞大师的
  1. (defun Rand (nMin nMax / seed)                              ;系统变量为种子定义的随机函数      (setq seed (getvar "USERR4"))
  2.       (if (zerop seed)
  3.         (setq seed (getvar "TDUSRTIMER")                        ;"CPUTICKS" "CDATE"均可为种子
  4.               seed (- seed (fix seed))
  5.               seed (rem (* seed 86400) 1)
  6.         )
  7.       )
  8.       (setq seed (rem (+ (* seed 15625.7) 0.21137152) 1))
  9.       (setvar "USERR4" seed)
  10.       (+ nMin (* seed (- nMax nMin)))
  11.     )
 楼主| 发表于 2016-10-24 13:59 | 显示全部楼层
;;;测试函数
(defun testnew2(x / tmp s0 s1 s2 s3 s4 s5 s6 s7 s8 s9)
(setq s0 0)
(setq s1 0)
(setq s2 0)
(setq s3 0)
(setq s4 0)
(setq s5 0)
(setq s6 0)
(setq s7 0)
(setq s8 0)
(setq s9 0)
(repeat        x
  (setq tmp (Rand 0 1))
  (cond
    ((< tmp 0.1) (setq s0 (1+ s0)))
    ((< tmp 0.2) (setq s1 (1+ s1)))
    ((< tmp 0.3) (setq s2 (1+ s2)))
    ((< tmp 0.4) (setq s3 (1+ s3)))
    ((< tmp 0.5) (setq s4 (1+ s4)))
    ((< tmp 0.6) (setq s5 (1+ s5)))
    ((< tmp 0.7) (setq s6 (1+ s6)))
    ((< tmp 0.8) (setq s7 (1+ s7)))
    ((< tmp 0.9) (setq s8 (1+ s8)))
    ((< tmp 1.0) (setq s9 (1+ s9)))
  )
)
(princ "\n")
(princ s0)
(princ " ")
(princ s1)
(princ " ")
(princ s2)
(princ " ")
(princ s3)
(princ " ")
(princ s4)
(princ " ")
(princ s5)
(princ " ")
(princ s6)
(princ " ")
(princ s7)
(princ " ")
(princ s8)
(princ " ")
(princ s9)
(princ " ")
(princ "\n")
)
结果:
(testnew2 100000)
10062 10108 9975 10017 9956 9889 9951 9950 10032 10060
9916 9989 9961 10250 10083 10120 9984 9923 10016 9758
9935 9948 10151 9981 9945 9910 10116 10034 9897 10083
这个看起来不错,均匀分布的,只是自动是6位小数,我实在是看不出来6位小数的10的6次方的所有可能的值是不是都能取到。。。。,不过实际用应该没有问题
谢谢 xyp1964大师 自贡黄明儒大师 高飞大师
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-4-25 09:11 , Processed in 0.570732 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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