推 tonyxfg: 你應該多跑幾次一億抽來做比較才對,這數值看起來就是正 11/28 09:22
→ tonyxfg: 常的誤差範圍而已,很難說服人一定是這樣啊... 11/28 09:22
這實驗蠻花時間的勒,跑1億抽要十幾個小時...
其實這也可以看成我做了100次100萬抽的實驗呀?
我有把程式附在後頭,有興趣的人可以自己試看看...
不過... 我覺得... 與其多跑幾次實驗,
還不如去看一下計算機結構跟隨機函數的設計原理... ^^;
→ j9145: 你一開始就搞錯前題。 11/28 09:28
→ j9145: 不是為什麼要搞這麼複雜,而是必須這麼複雜。 11/28 09:29
→ j9145: 你要先搞清楚轉蛋遊戲的轉蛋機就是最大營利項目,多花資源 11/28 09:30
→ j9145: 去維護很合理吧? 11/28 09:31
去把原本就已經很好的 1.000027% 調整成完美的 1% 嗎?
我還蠻難想像會有遊戲公司這麼做就是了... 能不能做到也是個問題...
轉蛋遊戲最大的營利手段,靠的不是完美的1%,而是活動內容跟卡牌設計吧...
與其花資源去追求高精密度亂數,多找兩個繪師把妹子畫美一點會不會比較有用?
噓 Xavy: 又來了,又活在自己世界了 11/28 09:39
→ j9145: 所以你找畫師來設計轉蛋機機率? 11/28 09:39
我的意思是... 你需要隨機的時候,寫一行 r = random() 就夠了,不用想太多
推 lanjack: 遊戲廠商:反正有沒有差那一點點機率玩家又不可能知道, 11/28 09:40
→ lanjack: 有卡面強度就有人抽。不爽拿證據吉我啊~ 11/28 09:40
→ dreamnook: 我已經搞不懂這串到底是在討論什麼了 官方有無作弊嗎XD 11/28 09:43
官方根本沒必要作弊吧... 說到底,玩家抽不到卡,對營運未必是好事啊
又不是所有玩家都信抽到有教,也是有抽不到就崩潰刪遊戲的啊... ( ̄▽ ̄#)﹏﹏
推 Cyjustin: j大是當工程師是神嗎,機率越複雜程式越難搞 11/28 09:49
→ Cyjustin: 搞出來都東西還有一定的誤差範圍,真的沒必要 11/28 09:51
→ lkzax: 如果1E抽要跑十幾個小時 有10萬人同時按10連是要跑60秒? 11/28 09:51
之所以要跑十幾個小時,因為我的抽法是抽一張心抽時,要先抽30張友抽,
確定30抽都摃龜之後,才會去抽一張心抽。
友情抽30連可能要好幾次才會有有一次全槓,這時才抽一張心抽,所以才要這麼久。
→ lkzax: 這樣要多少台電腦才夠? 11/28 09:52
推 e2167471: 有實驗有推 不無可能吧 反正對玩家來說都是黑盒子 11/28 09:57
→ e2167471: 說這個可能 和說這個不可能的荒謬程度是類似的XD 11/28 09:58
→ e2167471: 更何況先確定30抽共龜才去抽並不是很容易的做法 11/28 09:58
→ e2167471: 我是不覺得遊戲公司會為了維護萬分之三的機率去防這個 11/28 09:59
真的... 與其防止玩家抽到,不如先解決一下那些萬分之三,
幾百抽抽不到山翁的問題...
抽到的人以後還會抽別的,但抽不到而崩潰的人就不一定了...
→ lkzax: 30抽沒中的機率約為0.2 反推回去 總抽數約為5.65E多 11/28 10:05
→ lkzax: 這樣10萬人同時按10連也是要跑10秒 這樣算合理嗎? 11/28 10:06
剛才算了一下,我的電腦產生100萬筆隨機數字要花 2.38 秒
實際運作還要加上其他迴圈、條件控制、函式進出堆疊、資料庫讀寫什麼的,
要10秒也是有可能吧,不過上雲端的服務,不會是我這樣單台電腦在運作就是了
def calcRandomTime(nRound):
tStart = time.time()
for i in range(nRound):
r = random.randint(1, 100)
tEnd = time.time()
print('time spend:', tEnd - tStart)
if __name__ == '__main__':
calcRandomTime(1000000)
→ lkzax: 就算先抽友抽再抽石抽也才提升萬分之三 實在很雞肋 11/28 10:08
推 Cyjustin: 合理,所以通常人數過多就會有伺服器分流 11/28 10:10
→ intela46585: 如果我在廁所跑這程式 出來機率多個百萬分之一 11/28 10:15
→ intela46585: 我是不是也可以主張在廁所抽會提升機率... 11/28 10:15
要符合這實驗規模的話,你得要上很多次廁所,
然後你也要同時在廁所以外的地方跑多次同樣的實驗,
如果得到在廁所真的會多百萬分之一的機率,我也會認同唷!!
→ intela46585: 這樣跑的結果 跟玄學有什麼差別? 11/28 10:16
我同意這實驗很粗糙,1萬次不夠,100萬次不夠,1億次不夠,永遠都不夠
其實最簡單就是去理解程式語言產生隨機數字的原理,
當你懂了 random() 的原理之後,就不會覺得這麼玄了
推 Cyjustin: 跟玄學差不多啊,畢竟沒脫離誤差範圍 11/28 10:26
→ shinchen: 是你對random的原理只懂一半吧...照你的實驗 第一個seed 11/28 10:30
→ shinchen: 從頭到尾不改變 第二個只用一台電腦一個thread抽 11/28 10:31
→ shinchen: 這兩個實際狀況都是不成立的 11/28 10:31
→ shinchen: 你的理論基礎是在同seed下亂數器會讓各數字出現率平均 11/28 10:32
→ shinchen: 但是當seed不定的時候這理論就不成立了 11/28 10:33
你在寫程式產生亂數的候會讓 seed 一直換來換去嗎?
正常來講應該不會吧,原本 random 序列已經有良好的特性了,
目標1%,跑了1億次得到1.000027%的結果,請問有什麼道理要去改 seed?
抽卡又不是一次花半小時,也不過就幾分鐘之內的事,
你跑一個隨機程式,卻每分鐘都在改 seed,
搞不好跑出來的序列隨機性比什麼都不做還要差吧... ._.
→ j9145: 沒時間打太多,直接貼文,重點是你能不能提升玩家付費比 11/28 10:39
→ dreamnook: 到後來反正覺得可以提升萬分之3來滿足心情也可以啦 11/28 10:40
→ j9145: 而不是機率到底有沒有1%,這篇文作者是業界待很久的企劃, 11/28 10:40
→ j9145: 只要你無法得知營運有沒有做手腳,那你一切玄學都是沒有意 11/28 10:41
→ j9145: 義的。 我要表達的就是這樣 11/28 10:41
既然1%機率對營運不是重點,他們就沒必要花時間在完美的隨機上,
處理隨機大半只是簡單的一行 r = random() 解決,不是嗎?
如此一來,利用隨機函式在程式上的特性,先用友抽去濾特定結果,
這是很科學的作法,你花點時間去理解計算機結構跟程式語言,就不會覺得這麼玄了。
我絕對是相信營運沒做手腳的,如果懷疑的話,根本就不會玩這遊戲 ^^;
有動手腳也是為了讓你更好抽... :p
→ j9145: 沒人規定友抽跟石抽一定是同樣公式XDDD 11/28 10:51
沒人這麼規定,但這樣最簡單
如同你剛才所說的,對遊戲公司而言,重點是能不能提升玩家付費比
完必沒必要多花資源去設計不同的公式來應付友抽跟石抽,
以一個小遊戲公司,每個月領那麼一點點薪水的工程師,
要做出比 1.000027% 更好的隨機函式根本是天方夜談,這部份不用想得太複雜了
→ j9145: 而且你肯定有沒有把文章看完,繼續用你的玄學試吧 11/28 10:51
推 Cyjustin: j大那篇講轉蛋機制設計,特定up跟保底本來就會有 11/28 11:03
推 Cyjustin: 但現在不是在討論那個吧? 11/28 11:06
→ gn00399745: seed只要用時間就代表示一直變動SEED了阿 11/28 11:07
→ Cyjustin: 更何況他描述的部分行為在日本還不是合法的 11/28 11:07
→ noob9527: 重點就是通常會用時間當seed 所以不會符合你的說法阿 11/28 11:16
我有點懷疑我們在講的是不是同件事...
所謂的 seed 是改變隨機生成器的種子,
你給定一個初始條件,然後用既定的演算法不斷迭代產生隨機數,
一般 seed 是用時間,沒錯,但這是初始時候的事,
初始階段過後,整個隨機序列就已經決定好了
如果他初始出來的隨機序列是 1, 3, 7, 11,
你第一次抽一定是1,第二次不管你是早上抽、晚上抽、廁所抽,都是3
附上簡單的程式供您做驗證
def genRandom(nRound):
listRandom = []
for i in range(nRound):
r = random.randint(1, 100)
listRandom.append(r)
print(listRandom)
if __name__ == '__main__':
random.seed(1)
genRandom(10)
→ gn00399745: 在c++上只要call的srand(seed) rand數列就改變了 11/28 11:18
→ noob9527: 那照你的說法 同seed 然後你先抽友抽30次 11/28 11:20
→ noob9527: 把你的UR抽抽掉 你回到石抽 抽UR機率也就更低了阿 11/28 11:20
策略是如果友抽中獎了,就不會去石抽,要繼續讓友抽連摃N次之後才會石抽
→ noob9527: 還是你友抽抽到R都會重開app重抽30次 那也算很閒了 11/28 11:22
不需要重開 app,抽獎的程式是在 server 端跑,跟你手機上的 app 無關
→ noob9527: 然後亂數的部分 時間當seed是非常正常的 11/28 11:23
當然都是用時間來當 seed,但我就問一句,你寫程式需要用到隨機時,
你會 seed 幾次?除了初始化那一次之外,你之後還會故意再 seed 第二次?
→ noob9527: server端處理完你的抽 下次當然就不同seed了 11/28 11:24
→ noob9527: 你如果說抽10連 那個10連是同個seed或許還有可能 11/28 11:24
→ noob9527: client斷開重新連你 你的server端當然重新初始化參數阿 11/28 11:27
呃... 我想請問... 這些想法...
你是真的都這樣寫程式... 還是... 用想像的... ( ̄ー ̄;)
→ noob9527: 在下孤陋寡聞 server端用php就這樣寫的 11/28 11:36
你會在 php server 端每次處理一個 request,
如果有需要用到隨機數字時,就執行一次 srand(time())?
我無法想像你這麼做的目的是什麼...
為了要讓同時連線進來的人,保證能隨機出相同的結果嗎?
→ noob9527: 如果你有更好的寫法 那就指導一下 11/28 11:36
→ noob9527: 而且php下rand就是直接給一個新的seed 我沒記錯的話 11/28 11:39
直接下 rand() 就好,其他的事不用多想
rand 是從已生成好的隨機序列拿一個出來,
但 seed 的意思則是要重新產生一組新的隨機序列,
我覺得程式在執行中,不管有多少新的連線進來都不應該去重新 srand()
人家的隨機序列是一堆天才設計出來的,
透過程序不斷去 srand(),只怕非但不能得到更好的隨機性質,反而有可能出包
→ gn00399745: 我懂你的做法 但...思考了以後這個機率提升很無感XD 11/28 11:39
→ noob9527: 目的是什麼... php就這樣阿 request結束 程式也結束 11/28 11:41
→ noob9527: 可是..新版php就是更新你講的那個 他會自動srand() 11/28 11:45
自動 srand(),是指你不需要操心初始化的動作,而不是時時在 srand
時時在 srand 這設計很危險,我現在就能想到一個可能性,
我可以先 srand() 未來的時間,比方說今天中午12點整好了
srand(time(今天中午12點整))
r = rand()
這時我就在本地端得到了 r 的結果,如果剛好是 0,
就準時發 request try 你的 server,看是拿到 R 卡還是 UR,
如果拿到 R,那我就再 try 另一個能獲得 100 結果的時間,
網站出隨機數字還卻一直在 srand,會有被預判攻擊的風險,
一般是不會這麼設計的
另外,一般來說,網路服務並不是一個連線進來就開一支程式,
他是一支一直在運行的程式,負責處理不斷湧進來的連線
→ noob9527: 但是php就是一個連線進來就開一個給他呀 11/28 12:10
→ noob9527: 什麼東西都要重新初始化 資料庫 參數 seed 11/28 12:11
→ noob9527: 你想把參數保留到下一個連線還有困難勒 11/28 12:12
呣... 我想你可能是對 seed 的認知有點誤會,或者跟一般的定義不太一樣
http://php.net/manual/en/function.srand.php
這裡剛好有個網頁在討論 php 的亂數怎麼做的
方法一
<?php
srand(5);
echo(rand(1, 10));
srand(5);
echo(rand(1, 10));
srand(5);
echo(rand(1, 10));
?>
方法二
<?php
srand(5);
echo(rand(1, 10));
echo(rand(1, 10));
echo(rand(1, 10));
?>
你兩個都拿去跑一下,就會理解為什麼 srand() 該在初始的時候做一次就好
新版 php 甚至把它做成自動的,省去你手動 srand 的需求,
因為,如果你是用時間做 seed,好死不死,
有使用者同時 request,他們會得到相同的結果,
初始化都要小心了,更別提每次 request 都重新下 seed
一直換 seed 並不會讓你的隨機數字更好,反而會有被預判攻擊的風險
→ noob9527: 你知道php有10個連線進來 方法二的srand()會執行10次嗎 11/28 12:28
對,所以完全不該這麼做,srand 不能寫在處理連線 request 的地方
→ noob9527: 當然同你講的 10個連線如果分秒不差 他會是同樣結果 11/28 12:29
→ noob9527: 而且你說服務只會使用同個seed 然後所有人都在抽 11/28 12:29
→ noob9527: 你的30抽友抽期間 也有一堆人在抽 UR搞不好早被抽走了 11/28 12:30
→ noob9527: 你根本沒辦法知道30抽的時間內有沒有其他人抽到 11/28 12:30
這完全不重要,其他人所有的行為都是隨機的,當成亂數的一部份即可。
一堆人搞不好會把UR抽走,也可能把R卡抽走呀
這個模型並不是看最近的10抽20抽的結果,
而是未來的一佰萬抽,一億抽之內,少掉最開頭30抽的效果
→ noob9527: 你不寫在連線request的地方要寫在哪...? 11/28 12:31
別寫,php 已經幫你考慮好了,不要自己做 srand
→ noob9527: 你這講法就問題點阿 你30抽沒中 未來中的機率更高沒錯 11/28 12:38
→ noob9527: 但是那機率高的部分不一定是你抽到的阿 隨時都有人在抽 11/28 12:38
→ noob9527: 機率偏高時 馬上就會被抽掉獎項 機率又會回到原本1% 11/28 12:39
→ noob9527: 在你把30抽沒中當做一個前提 就是賭徒論了 11/28 12:41
什麼叫做機率高的部份?未來的池是個整體呀...
不管怎麼抽,都沒辦法阻止別人去抽掉後面的UR,
先友抽唯一的功能,就只是讓序列刪掉最開頭30張R卡而已
我會在數列中,發生連續30張R卡之後的時間點切入,這策略就這樣而已
隨機時間切入的1億抽,跟等發生30張R卡之後的1億抽,
UR卡的濃度有些許的不同,這是用程式隨機的特性,瞭解這樣就夠了
→ noob9527: 會這樣說 就是因為你無法保證30抽中間是否有其他因素 11/28 13:12
→ noob9527: 在無法排除這些因素 你的策略就不成立 11/28 13:13
→ noob9527: 然後seed那塊 無論是php幫我處理好 還是自己srand 11/28 13:13
→ noob9527: 都還是每次執行就分配一個新seed 11/28 13:14
呃... 為什麼你這麼有把握啊...
php 的 interpreter 是你寫的嗎... 如果是的話我建議下版快點改掉,
每次執行都重新分配一個 seed 是非常不良的設計...
http://php.net/manual/en/function.srand.php
看一下這篇文章 hagen 回覆
It is REALLY essential to make sure that srand is called only once.
他甚至用了一些方法來保護 request handle 裡不會重覆呼叫 srand
<?php
if (!$GLOBALS["IHaveCalledSrandBefore"]++) {
srand((double) microtime() * 1000000);
}
?>
php 我是真的不熟,但是在 request 裡一直 srand 真的超出我的想像...
→ noob9527: 你架個簡單的server 跑一次網頁 你就知道為什麼了 11/28 13:28
→ noob9527: 程式碼也夠簡單 就一行沒其他<?php echo mt_rand();?> 11/28 13:29
→ noob9527: 然後你每次F5重整網頁 就是一個新的執行 11/28 13:30
my_rand() 只是在產生亂數而已,他並沒有一直改 seed
→ noob9527: 就程式第一次執行php會自動幫你配seed呀.. 11/28 13:33
Yes,這個動作只做了一次,之後就不會再做了,
當你第一次執行時,未來所有的亂數數列也被決定好了,
並不會有什麼每次 request 就分配一個新seed這種事
→ noob9527: <?php if($a==null){$a=1;} $a++; echo $a;?> 11/28 13:41
→ noob9527: 以這例子 你覺得這行執行10次分別會輸出多少? 11/28 13:42
→ noob9527: 再看看上面的mt_rand() 執行10次 你覺得會是怎樣? 11/28 13:46
→ noob9527: 也沒什麼特別的 就單純網頁跟服務是不一樣的執行方式 11/28 13:47
這跟 seed 有關係嗎?不管 mt_rand() 執行了幾次,他的 seed 是同一個,
得要先把這基本的觀念建立好才行
→ noob9527: 我想我很難跟你解釋每次執行時 seed都會不存在的問題 11/28 13:52
當然很難解釋,因為根本就不是這樣
php rand() 怎麼運作的?看這裡
https://www.w3schools.com/php/func_math_rand.asp
PHP 4.2.0: Random number generator is seeded automatically
php 2.4 後會自動幫你 seed,但你把這段話腦補成每次 rand 都會下 seed,
不是的,他只有在第一次(或者是服務初始時)才會播一次 seed,以後就不會變了
如果對 srand 的原理還有疑惑,可以看這裡,中文的
http://libersky.tumblr.com/post/64149021859/c-randsrand
※ 編輯: archon (118.161.36.233), 11/28/2017 19:29:32