|
引用 | 編輯
冷場館女僕長
2025-05-03 14:25 |
樓主
▼ |
||
|
圖 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至20範圍內的數字, random() 整體在速度上會比 random_num() 快 ,如果你喜歡運行速度快 )![]() ----------------------------------------- 但random()只能抽「 0 至 max-1」的條件下,會有許多情況下也不適用, ![]() 所以在這分享一些從網上找到的公式,令 random() 整體實用性提升 :random_chance 複製程式 #define random_chance(%0) (%0 > random(100)) 0.000096780092檢查機率百分比,若抽中了會回傳1,反之則回傳0, 由於不需運算所以效能跟本身 random() 幾乎沒差別 random_fastgetnum 複製程式 #define random_fastgetnum(%0,%1) (random(%1 - %0 + 1) + %0) 0.000091732720可以抽取 %0 至%1 範圍內的數字,但只限正整數 random_sighnum 複製程式 #define random_sighnum(%0) (random(2 * %0 + 1) - %0) 0.000106322552可以抽取 0 至 %0 範圍內的數字,並會隨機將數字轉為正數或負數 random_getnum 複製程式 #define random_getnum(%0,%1) (%0 + (random(RAND_MAX) % (%1 - %0 + 1))) 0.000149931260相比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)) 0.000478622104這個可以抽取 %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)) 0.000258840008可以抽取 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) 0.000356375972可以抽取 %0至%1 範圍內的小數 但缺點同上,同樣只提供给大家參考用 -------------------------------------------------------- 如果你看完對random()有興趣想試試看, ![]() 你可以下載在1樓的附件random.inc, 在自己源碼加上#include <random>便可使用上面的define了~ ![]()
|
|||
|
引用 | 編輯
冷場館女僕長
2025-05-26 16:47 |
1樓
▲ ▼ |
||||||||||
|
更新一下帖文,常常聽說有人說數學只需懂加減乘除即可
,但我弄完這些總覺得我連加減乘除也搞不太懂( ![]() 從之前的小數運算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更新後random_getfloat(0.0,20.0) 執行10000次的速度 : 0.0002472922240更新後random_slowgetnum(-20,20) 執行10000次的速度 : 0.000420149320 可以看到,雖然效能上仍跟原生random_float慢(randomf性能可接近但功能性較弱), 但會比之前直接用除法快 ![]() ![]() 已把更新後的random.inc放到附件裡 ![]()
|
|||||||||||