广告广告
  加入我的最爱 设为首页 风格修改
首页 首尾
 手机版   订阅   地图  繁体 
您是第 638 个阅读者
 
发表文章 发表投票 回覆文章
  可列印版   加为IE收藏   收藏主题   上一主题 | 下一主题   
冷场馆女仆长 会员卡
个人头像
个人文章 个人相簿 个人日记 个人地图
特殊贡献奖
头衔:一位兴趣使然的伺服主一位兴趣使然的伺服主
特约版主
级别: 特约版主 该用户目前不上站
版区: CS教学区
推文 x201 鲜花 x478
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片
推文 x0
[插件] 一些关于 native random() 实用公式  (可令random()抽正负数、小数等等)

图 1. 附一张图文不符的图   
附一张图文不符的图



相信大家稍微看过AMXX函数的也会知道,
AMXX有三种函数可以生成随机数字:
复制程式
native random(max)  //可以抽取 0 至 (max - 1)  范围内的整数

native Float:random_float(Float:a, Float:b);  // 可以抽取 a 至 b 范围内的小数

native random_num(a, b)  // 可以抽取 a 至 b  范围内的正负整数
乍看一下没啥分别也是产生随机数字
但其实两者在运作上不相同:
random_float 、random_num是直接向引擎获取随机数
而random()则是使用AmxModx内置生成随机数

你问我知道这些有啥用? 呃,没错的确听起来没啥用表情
不过既然两者实现方式不同,那执行速度上可能就有差别喔...?表情
以下是使用分析器分别执行10000次测试出来:
random(20) time :
0.000093187176
0.000094055468
0.000090957132

random_num(0,20) time :
0.000162057616
0.000242643696
0.000160149244

random_float(0.0,20.0) time:
0.000151322136
0.000199439368
0.000146716752
从结果可见,同样是抽取0至20范围内的数字, random() 整体在速度上会比 random_num() 快表情
如果你喜欢运行速度快(即使你完全体感不出来表情),你可能会想选择用random() 表情

-----------------------------------------

但random()只能抽「 0 至 max-1」的条件下,会有许多情况下也不适用,表情
所以在这分享一些从网上找到的公式,令 random() 整体实用性提升表情:

random_chance
复制程式
#define random_chance(%0) (%0 > random(100))
random_chance(25) 执行10000次的速度 :
0.000096780092
0.000096626784
0.000093949460
检查机率百分比,若抽中了会回传1,反之则回传0,
由于不需运算所以效能跟本身 random() 几乎没差别

random_fastgetnum
复制程式
#define random_fastgetnum(%0,%1) (random(%1 - %0 + 1) + %0)
random_fastgetnum(0,20) 执行10000次的速度 :
0.000091732720
0.000110157688
0.000091345996
可以抽取 %0 至%1 范围内的数字,但只限正整数

random_sighnum
复制程式
#define random_sighnum(%0) (random(2 * %0 + 1) - %0)
random_sighnum(20) 执行10000次的速度 :
0.000106322552
0.000105548456
0.000127152180
可以抽取 0 至 %0 范围内的数字,并会随机将数字转为正数或负数


random_getnum
复制程式
#define random_getnum(%0,%1) (%0 + (random(RAND_MAX) % (%1 - %0 + 1)))
random_getnum(-20,20) 执行10000次的速度 :
0.000149931260
0.000141040200
0.000122050440
相比random_fastgetnum,这个可以抽取 %0 至%1 范围内的正负整数,
所以用途很广泛,但因要进行% 运算所以执行速度较慢 (接近random_num所需效能)
如果你是以效能优先,建议跟 random_fastgetnum、random_sighnum 灵活配合运用

random_slowgetnum
复制程式
#define random_slowgetnum(%0,%1) (floatround(((float(random(RAND_MAX)) / float(RAND_MAX) * (%1 - %0 + 1)) + %0), floatround_floor))
random_slowgetnum(-20,20) 执行10000次的速度 :
0.000478622104
0.000423543492
0.000444157876
这个可以抽取 %0 至%1 范围内的正负整数,
但由于需进行不少浮点数运算,所以执行速度是所有公式之中最慢,
好处是由于将要抽的数字拆分成0.0至1.0小数,然后再运算得出范围内的整数,
所以"可能"体感上抽取数字会更均匀一点,就好像 random(2) 和 (random(50) > 25) 体感上后者数字更随机,即使机率一样,
而且你可以避免因%不能整除某数而令某些数字出现机率"高一点点",
但以上的好处其实并不明显,所以除非你有特别需求,
否则整体上建议使用random_getnum就好

randomf
复制程式
#define randomf(%0) (Float:((float(random(RAND_MAX)) / float(RAND_MAX)) * Float:%0))
randomf(20.0) 执行10000次的速度 :
0.000258840008
0.000240448800
0.000254451900
可以抽取 0至 %0 范围内的小数,但因为要进行浮点数除法,
所以会被原生random_float慢,
要不要使用就自己衡量,这里只提供给大家参考用

random_getfloat
复制程式
#define random_getfloat(%0,%1) (Float:(float(random(RAND_MAX)) / float(RAND_MAX) * (Float:%1 - Float:%0)) + Float:%0)
random_getfloat(0.0,20.0) 执行10000次的速度 :
0.000356375972
0.000366431980
0.000398652484
可以抽取 %0至%1 范围内的小数
但缺点同上,同样只提供给大家参考用

--------------------------------------------------------

如果你看完对random()有兴趣想试试看,表情
你可以下载在1楼的附件random.inc,
在自己源码加上#include <random>便可使用上面的define了~表情


[ 此文章被冷场馆女仆长在2025-05-26 17:11重新编辑 ]



我只是一个兴趣使然的Server主.
献花 x0 回到顶端 [楼 主] From:未知地址 | Posted:2025-05-03 14:25 |
冷场馆女仆长 会员卡
个人头像
个人文章 个人相簿 个人日记 个人地图
特殊贡献奖
头衔:一位兴趣使然的伺服主一位兴趣使然的伺服主
特约版主
级别: 特约版主 该用户目前不上站
版区: CS教学区
推文 x201 鲜花 x478
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

更新一下帖文,常常听说有人说数学只需懂加减乘除即可表情
但我弄完这些总觉得我连加减乘除也搞不太懂( 表情

从之前的小数运算define可以看出,因为需使用除法而令整个define跑得相当慢,
但存不存在改良的方案?答案是有的表情
在程式语言中, / 除法运算是比 * 乘法运算消耗更多资源,
但我们可以透过 * 乘法来做出 / 除法的效果,从而减轻资源消耗表情
简单举个例子,4 * 0.5 结果会等于 2,可看到我们使用的是乘法但相等于把数字除以2表情
而我们也可以透过上述‘’取巧‘’的乘法技巧来改善浮点数除法较慢的问题,
首先,所以我们预先自己使用计算机计算 1.0 / RANDMAX(即是0x7FFFFFFF) 的结果:

好了,我们得出其数值为 4.656612875245797e-10
然后把这数值把本来进行除法替代成乘法表情:
新增:
复制程式
//Max inverse size, same as (1.0/0x7FFFFFFF), Used to create Random Float
//32位下最大反转数值大小, 等同 (1.0/0x7FFFFFFF), 用来产生随机浮点数
#define INV_MAX 4.656612875245797e-10
然后修改:
复制程式
修改前:
#define randomf(%0) (Float:((float(random(RAND_MAX)) / float(RAND_MAX)) * Float:%0))
#define random_getfloat(%0,%1) (Float:(float(random(RAND_MAX)) / float(RAND_MAX) * (Float:%1 - Float:%0)) + Float:%0)
#define random_slowgetnum(%0,%1) (floatround(((float(random(RAND_MAX)) / float(RAND_MAX) * (%1 - %0 + 1)) + %0), floatround_floor))

修改后:
#define randomf(%0) (Float:((float(random(RAND_MAX)) * INV_MAX) * Float:%0))
#define random_getfloat(%0,%1) (Float:(float(random(RAND_MAX)) * INV_MAX * (Float:%1 - Float:%0)) + Float:%0)
#define random_slowgetnum(%0,%1) (floatround(((float(random(RAND_MAX)) * INV_MAX * (%1 - %0 + 1)) + %0), floatround_floor))
更新后

更新后randomf(20.0) 执行10000次的速度 :
0.000155862280
0.000156527456
0.000156936260
更新后random_getfloat(0.0,20.0) 执行10000次的速度 :
0.0002472922240
0.0001932299120
0.0002426469200
更新后random_slowgetnum(-20,20) 执行10000次的速度 :
0.000420149320
0.000425449232
0.000464830904

可以看到,虽然效能上仍跟原生random_float慢(randomf性能可接近但功能性较弱),
但会比之前直接用除法快表情表情

已把更新后的random.inc放到附件里表情


本帖包含附件
zip random inc.zip   (2025-05-26 16:47 / 2 KB)   下载次数:0


我只是一个兴趣使然的Server主.
献花 x0 回到顶端 [1 楼] From:未知地址 | Posted:2025-05-26 16:47 |
sot86217
个人文章 个人相簿 个人日记 个人地图
小人物
级别: 小人物 该用户目前不上站
推文 x0 鲜花 x6
分享: 转寄此文章 Facebook Plurk Twitter 复制连结到剪贴簿 转换为繁体 转换为简体 载入图片

2025居然还有教学文 不支持不行 !


献花 x1 回到顶端 [2 楼] From:欧洲 | Posted:2025-05-27 11:47 |

首页  发表文章 发表投票 回覆文章
Powered by PHPWind v1.3.6
Copyright © 2003-04 PHPWind
Processed in 3.638976 second(s),query:16 Gzip disabled
本站由 瀛睿律师事务所 担任常年法律顾问 | 免责声明 | 本网站已依台湾网站内容分级规定处理 | 连络我们 | 访客留言