latest #14
アルターエゴ mode LPH
9 months ago @Edit 9 months ago
在河道上朋友的噗裡提了這裡就再提一次: 照新聞稿裡這樣寫看起來, 廠商的 bug 應該有兩個
一是權重加總前先取了唯一值,也就是所有參加 1 次的人只加一個 1,這會造成總權重比原來應有的權重要小,即是抽獎的判斷機率值變大
另一個這個我從字面上還是不甚確定實際狀況如何,但我的解讀是:程式將參加者由大權重排到小權重,然後對每個人以「該人權重除以上述總權重」為機率抽一次是否中獎,中獎就結束。就算總權重算對了這個做法也是錯的:應該要「除以總權重扣除前面未中獎的權重和」才對。可以看到這顯著的縮小了排在後面參加者的中獎機率,因為後面中獎會需要前面都不中,但這演算法沒把前面不中的部份扣掉
我其實有點覺得後面這個寫法的 bug 被前面的總權重 bug 給蓋住了,以致於廠商在測試時由於兩個 bug 的連續影響的關係都沒有發現問題:由於前一個 bug 使每個人的判定機率變大了,後一個 bug 的症狀「跑完所有人都沒人抽中」的機率下降,造成廠商以為程式每次抽都有人抽中就沒有發現問題
名無乚
9 months ago
好貴的bug啊
立即下載
JokerCatz
9 months ago
沒那麼複雜,看內文應該是 100 個人排序後每個人骰骰子,前面的中了後面的人就沒機會骰了

這題的重點應該是每個獎項都只能骰一次,或是 100 個人按照加權骰 100 次,挑出第一輪後,第二輪後用平均機率來骰即可
> 前面的中了後面的人就沒機會骰
只要骰的機率是對的這個做法也不會有問題,重點在於後面的人在骰的機率要因應前面的人沒中而相應減少分母
簡單舉例應該比較能理解:假設 3 個人同權數 (不失一般性都是 1),第一個人骰 1/3 沒問題,但若第一個人沒骰中輪第二個人時,他得骰 1/2 才對,這個 1/2 也沒中再輪第三個人骰 1/1 即必拿,這樣三個人的中獎機率都是 1/3
原文裡寫的錯誤做法變成這裡的三個人都骰 1/3 (假設總權數修正了)
JokerCatz
9 months ago
這題有加權的 ... 上述的計算方式會變得過於複雜,就是寫錯的原因了 ...

如果人數變成 100 萬時,小數點後面的零的裁切就會變成不公平的原因
JokerCatz
9 months ago
所以才說這題最簡單的解法就是全數展開然後排序,然後 N 取 1 瞬間就結束了,每個獎項骰一次即可
於是新聞稿中描述的做法不是取浮點數,而是取 1 到總權數 (分母) 中的隨機整數後與權數比較

對,確實要抽加權獎有更簡單的方法 (甚至如你所說取一個至總權數為止中間的亂整數,再算權數和數過去也行),但我在說的是若要走這個演算法的話機率該怎麼算才對
而一個簡單的調整只需要把總權數分母扣掉每次沒抽中的人的權數就行了
アルターエゴ mode LPH
9 months ago @Edit 9 months ago
(我這裡自然假設取亂整數是均勻的,但這一點當然也是一個很容易錯的地方)
JokerCatz
9 months ago
其實我的解法和你的解法基本上是一致的,最慘都是全歷遍,初始動作都是先取 sum 後,你的需要把分母扣除後一直骰,我只需要一個 rand 然後一直扣就好了 ... 兩者都能提早結束,而我的解法比你輕量很多才是 ...

從無到有到現在在外商,最終工程師們都會選擇簡單粗暴的方式。沒有炫技,一切求穩 ... 不然類似這種沒寫好整間公司就掰了,嘛,心裡負擔很大的,不是嘴砲而已
> 選擇簡單粗暴的方式
在「選擇」這件事上我也同意,能求穩誰不想求穩;但什麼是「簡單粗暴的方式」在各人眼中其實各有不同,我的簡單方式你可能要繞一圈,你的簡單方式我可能要想一下。(看了三年的 Advent of Code reddit 文章對這一點非常有感)
所以在「已有程式的問題修正」這一點上,我會傾向沿著原有程式的邏輯進行修正,實在不行才去做打掉重練的事,這才是為什麼我會說「bug 是在機率算錯」上面而不是「bug 是用了『複雜』的演算法」的原因
back to top