伊莉討論區

標題: 作弊骰子:出現 1、2、3 的機率是 4、5、6 的 1.1 倍 [打印本頁]

作者: 鄭偉博    時間: 2017-5-5 04:08 PM     標題: 作弊骰子:出現 1、2、3 的機率是 4、5、6 的 1.1 倍

本帖最後由 鄭偉博 於 2017-5-5 04:08 PM 編輯

[attach]118669212[/attach]
[attach]118669217[/attach]
題目要求要將產生的點數印出來且要證明擲出123的機率是擲出456機率的1.1倍

我不知道如何改變骰子擲點數的機率....我思考的方向也很混亂....



作者: kauhia3440    時間: 2017-5-5 09:59 PM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: 鄭偉博    時間: 2017-5-6 01:18 AM

本帖最後由 鄭偉博 於 2017-5-7 03:29 PM 編輯
kauhia3440 發表於 2017-5-5 09:59 PM
假如擲63次骰子
出現11個1點
11個2點

那可以假設擲出21次嗎1  5次
2  5次
3  1次
4  3次
5  3次
6  4次

作者: kauhia3440    時間: 2017-5-10 01:07 PM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: ash1326    時間: 2017-5-11 02:18 AM

本帖最後由 ash1326 於 2017-5-11 02:56 AM 編輯

你沒有使用srand,這樣只有亂數表,沒有影響因子

也就是說不管怎麼跑,結局永遠不變

還有code別貼圖檔...這樣沒人會想幫你run
作者: 鄭偉博    時間: 2017-5-11 09:49 AM

ash1326 發表於 2017-5-11 02:18 AM
你沒有使用srand,這樣只有亂數表,沒有影響因子

也就是說不管怎麼跑,結局永遠不變

我們老師只教我們用RAND沒有教我們SRAND...
不好意思我是第一次發文看別人也是用圖檔的...謝謝指教
作者: ash1326    時間: 2017-5-11 12:47 PM

鄭偉博 發表於 2017-5-11 09:49 AM
我們老師只教我們用RAND沒有教我們SRAND...
不好意思我是第一次發文看別人也是用圖檔的...謝謝指教 ...

如果你是想要絕對機率1.1的話

3樓的寫法可以更改成先抽出21個不重複亂數(1~21)

然後數字<=11的,就使用 rand()%3+1

抽到數字 12~21,就使用 rand()%3+4

這樣就保證擲出123的機率會等於456的1.1倍
作者: 鄭偉博    時間: 2017-5-11 01:21 PM

ash1326 發表於 2017-5-11 12:47 PM
如果你是想要絕對機率1.1的話

3樓的寫法可以更改成先抽出21個不重複亂數(1~21)

謝謝ash1326,可是我想再請問一下為什麼要用3呢?
作者: weirdococo    時間: 2017-5-12 10:43 AM

use v6;

my %construct = 1..6 Z=> 11/63, 11/63, 11/63, 10/63, 10/63, 10/63 ;
my @gonnaPick is default(0);
for %construct -> $pair {
        @gonnaPick.push( (loop { $pair.key })[ ^ $pair.value.numerator] );
}
@gonnaPick = ( @gonnaPick ).List.flat();

my %count;
for ^10000 {
        my $buffer = @gonnaPick.pick(1);
        " $_ time, we pick $buffer".say;
        %count{ $buffer }++;
}

say %count;
say qq:to/END/;
1 = { %count{1} } times, rate is {  %count{1} / [+] %count.values }
2 = { %count{2} } times, rate is {  %count{2} / [+] %count.values }
3 = { %count{3} } times, rate is {  %count{3} / [+] %count.values }
4 = { %count{4} } times, rate is {  %count{4} / [+] %count.values }
5 = { %count{5} } times, rate is {  %count{5} / [+] %count.values }
6 = { %count{6} } times, rate is {  %count{6} / [+] %count.values }
END

補充內容 (2017-5-12 10:57 AM):
這是用perl寫的版本,C語言的貼不太上來,太多敏感字!!反正改寫也是不錯的練習(為自己找藉口)!

補充內容 (2017-5-12 11:19 AM):
反正大家說,C語言包括了所有概念,會C語言其他語言都看得懂(藉口其二)!
作者: 鄭偉博    時間: 2017-5-12 03:14 PM

weirdococo 發表於 2017-5-12 10:43 AM
use v6;

my %construct = 1..6 Z=> 11/63, 11/63, 11/63, 10/63, 10/63, 10/63 ;

我只是個大一上程設不到一個學期的蔡菜鳥阿Q
作者: weirdococo    時間: 2017-5-12 04:30 PM

鄭偉博 發表於 2017-5-12 03:14 PM
我只是個大一上程設不到一個學期的蔡菜鳥阿Q

#那我加上解說
use v6;

#產生一個hash,有六個key分別是一 到 六,內容分別是抽到他的機率。
my %construct = 1..6 Z=> 11/63, 11/63, 11/63, 10/63, 10/63, 10/63 ;
#用那一個hash來初始化一個array,看齊來大概是 11 個 1 、 11 個 2 ..... 10 個 6
my @gonnaPick is default(0);
for %construct -> $pair {
        @gonnaPick.push( (loop { $pair.key })[ ^ $pair.value.numerator] );
}
@gonnaPick = ( @gonnaPick ).List.flat();

#再做一個hash,拿來計數,像是抽到1的時候 1的直就加一。
#然後在從剛剛那一個array裡面隨機抽取一個,做10000 次。
my %count;
for ^10000 {
        my $buffer = @gonnaPick.pick(1);
        " $_ time, we pick $buffer".say;
        %count{ $buffer }++;
}

say %count;

#印出結果
say qq:to/END/;
1 = { %count{1} } times, rate is {  %count{1} / [+] %count.values }
2 = { %count{2} } times, rate is {  %count{2} / [+] %count.values }
3 = { %count{3} } times, rate is {  %count{3} / [+] %count.values }
4 = { %count{4} } times, rate is {  %count{4} / [+] %count.values }
5 = { %count{5} } times, rate is {  %count{5} / [+] %count.values }
6 = { %count{6} } times, rate is {  %count{6} / [+] %count.values }
END

補充內容 (2017-5-12 04:34 PM):
這個網站C、C++貼不上來,真的很麻煩。

補充內容 (2017-5-12 04:37 PM):
用perl寫最好的優點就是這個網站貼得上來!

補充內容 (2017-5-12 04:40 PM):
在不行,考慮上C++的圖片!
作者: ren1244    時間: 2017-5-12 05:27 PM

關於貼程式碼的問題,可以參考版規喔:
http://www17.eyny.com/thread-8627739-1-1.html (2F有提供兩個允許貼程式碼的外部網址)

對於發問的文章,我覺得會想讓人處理的優先次序是:
文字檔程式碼 > 圖片程式碼 > 都沒給code
(當然也會考慮問題內容跟發問者是否有提供想法)

下面基本上是照2F想法寫的,不過不用 if...else ,直接用計算的方式得出幾點。
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>

  4. #define DICETIMES 1000000
  5. #define eyny_print printf

  6. int main()
  7. {
  8.         int i,r,count[6]={0};
  9.         srand(time(NULL));
  10.         for(i=0;i<DICETIMES;++i)
  11.         {
  12.                 while((r=rand())>=RAND_MAX/63*63);
  13.                 r%=63;
  14.                 ++count[r<33?r/11:3+(r-33)/10];
  15.         }
  16.         for(i=0;i<6;++i)
  17.                 eyny_print("%d: %d times...%.2lf%%\n",i+1,count[i],(double)count[i]/DICETIMES*100.0);
  18.         return 0;
  19. }
複製代碼


作者: 鄭偉博    時間: 2017-5-12 08:04 PM

這是我和朋友想出來的
因為包括敏感內容所以用網頁貼上
http://codepad.org/0yqpSZwV
謝謝各位幫忙
因為會的東西真的很少所以有些程式碼我看不懂....
作者: weirdococo    時間: 2017-5-12 09:41 PM

把你寫的用perl寫了一遍,你會發覺長的一樣,有沒有這樣覺得!
  1. my %count;
  2. my @face = ( loop { 1 + [%] (rand * 100).round(1) , 63 , 6 } )[ ^100000 ];
  3. %count{ $_ }++ for @face;
  4. say %count;
  5. "1.2.3的總數除以4.5.6的總數 = { ([+] %count{1..3} ) / ([+] %count{4..6}) }".say;
複製代碼
run code online
還有你寫的版本比我的好,我的是硬做出了的!
作者: 鄭偉博    時間: 2017-5-12 10:53 PM

鄭偉博 發表於 2017-5-12 08:04 PM
這是我和朋友想出來的
因為包括敏感內容所以用網頁貼上
http://codepad.org/0yqpSZwV

謝謝!!!這樣變得好簡短><

srand(time(NULL));
這行我也不是很懂,老師只教我們用RAND而且也只是用來做這題所以就只是叫我們這題要用這個打而已,
我同學有跟我解釋但我不是很懂,因為亂數%63後就只剩下0~62,再6個6個一數就會剩下3個1.2.3
我覺得這樣想很怪...不太懂Q
作者: ren1244    時間: 2017-5-13 05:14 PM

%6是說取6的餘數,所以:

x%6

x

個數

0

0, 6,12,18,24,30,36,42,48,54,60

11

1

1, 7,13,19,25,31,37,43,49,55,61

11

2

2, 8,14,20,26,32,38,44,50,56,62

11

3

3, 9,15,21,27,33,39,45,51,57

10

4

4,10,16,22,28,34,40,46,52,58

10

5

5,11,17,23,29,35,41,47,53,59

10


#define eyny_print printf
代表下面程式碼遇到 eyny_print 會用 printf 取代
寫這行只是因為伊莉遇到 printf加括號 會視為敏感字
所以透過這方法貼程式碼而已
你只要把下面的 eyny_print 都看成 printf 就可以了
同理:
#define DICETIMES 1000000
只要把後面的 DICETIMES 都看成 1000000 就可以了
用這技巧可以很方便的修改想要跑的迴圈數
相關章節:巨集(macro)

至於 srand 方面
你可以試看看不加 srand 下,你每次跑出來的結果是不是都一樣?
這是因為絕大多數程式語言的亂數都是偽隨機
也就是利用某種數學式計算出來的結果
而 srand 很像是指定起始點
srand(起始點位置)
而 time(NULL) 則是取得現在的時間
srand(time(NULL)) 就是以現在的時間做為起始位置
這樣更有隨機的感覺

作者: 炽天使    時間: 2017-6-3 04:31 PM

鄭偉博 發表於 2017-5-12 10:53 PM
謝謝!!!這樣變得好簡短><

srand(time(NULL));

srand(time(NULL));
這個是一個亂排的公能如果你不要它重復你要自己加ifelse
作者: 炽天使    時間: 2017-6-5 08:05 PM

熾天使 發表於 2017-6-3 04:31 PM
srand(time(NULL));
這個是一個亂排的公能如果你不要它重復你要自己加ifelse

ifelse要看你的條件,如過你不要它重復就用forloop和ifelse
作者: 炽天使    時間: 2017-6-5 08:19 PM

熾天使 發表於 2017-6-3 04:31 PM
srand(time(NULL));
這個是一個亂排的公能如果你不要它重復你要自己加ifelse

你的答案應該有重復的,是嗎?
作者: chevylin0802    時間: 2017-6-5 09:42 PM

本帖最後由 chevylin0802 於 2017-6-5 10:34 PM 編輯

感覺有點怪
因為如果題目改成1,3,5的機率是2,4,6的1.1倍時
就不靈了
或者出得再難一點
1到6出現的機率
分別是1.3,1.5,1.2,1.1,1.0,0.9
那豈不是就掛了。

其實電子賭場經常做這種事
他們不會給你擲數百萬次的統計結果才出現那種機率
往往只有一百次的統計就要逼近預期的結果
甚至還可以遠端遙控機率
所以一定有更好的解法

作者: weirdococo    時間: 2017-6-6 09:38 AM

本帖最後由 weirdococo 於 2017-6-6 09:40 AM 編輯
chevylin0802 發表於 2017-6-5 09:42 PM
感覺有點怪
因為如果題目改成1,3,5的機率是2,4,6的1.1倍時
就不靈了

我的想法(演算)是,先造出一個1..N的成對資料(一個hash或是兩個array),
在由那個成對資料容合成為一個array(像是 1 2 3  => 0.1 0.2 0.3,把質
取最小連比,也就是 1 2 3  => 1 2 3,然後融合的array 就是 1 2 2 3 3 3),
然後在平均隨機挑選那融合出的array裡面的一個元素。
但是這樣的想法好像執行得很慢(cost 很高),還有質一定要屬於負整數(Z) 或是
實數(rational number),還要想辦法拓展到real number。
所以一定要有更好的解法
作者: chevylin0802    時間: 2017-6-6 11:53 AM

本帖最後由 chevylin0802 於 2017-6-6 12:04 PM 編輯
weirdococo 發表於 2017-6-6 09:38 AM
我的想法(演算)是,先造出一個1..N的成對資料(一個hash或是兩個array),
在由那個成對資料容合成為一個 ...

我想請你做一個實驗
連續兩次取出亂數之後
只取亂數的000~999之間的數字
兩個數字相減取絕對值
把它當成是最後結果
如此重覆跑100及1000次之後
計算看看百位數的0~9之間的個數是不是遠比單純只取亂數來得平均一些
把跑100次跟1000次所得到的百位數0~9次數統計的結果秀圖出來看看
這是為了改善只有單純使用srand(time(NULL))/rand()時必需取樣大量次數才能得到接近期望結果的方法之一

因為坦白講
機率學講得很清楚
每一次擲骰子1~6的每一個面為正面的機率
不會隨著擲的次數而改變
也就是前一次的結果不會影響到後一次的結果
所以大數量統計只是一種理論值
它無法帶給你每擲六次都會從1~6分別各出現一次的結果
而這就是我在講怪怪的問題點



作者: weirdococo    時間: 2017-6-6 06:03 PM

本帖最後由 weirdococo 於 2017-6-6 06:55 PM 編輯
chevylin0802 發表於 2017-6-6 11:53 AM
我想請你做一個實驗
連續兩次取出亂數之後
只取亂數的000~999之間的數字

先上結果
原始資料:[attach]119044143[/attach]
標準化:[attach]119044142[/attach]

因為我不太會寫C,所以其實把C的資料餵給一些script來處理畫圖。
還有因為1000的資料太少,我改成
亂數的000~999之間的數字
每兩比數字相減取abs(像是 1 2 3 4 就變成  1  1) {ps 我不知道為什麼要做這步驟}
秀出這筆資料的前1000筆。

上code
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>

  4. int main( ) {
  5.     srand(time(NULL));
  6.     while(1) {
  7.         print_f("%d\n", rand() );
  8.     }
  9. }
複製代碼

script side
  1. use v6;
  2. use SVG;
  3. use SVG::Plot;

  4. my $proc = run 'main.exe', :out;
  5. my @randList = lazy (loop { $proc.out.get });
  6. my @filter =  @randList.grep({  $_ < 1000 && $_ > 0  });
  7. my @target = lazy gather for @filter -> $a , $b  { take ($a - $b).abs  };

  8. sub stddev($x) {
  9.     sqrt
  10.         (.[2] += $x**2) / ++.[0] -
  11.         ((.[1] += $x) / .[0])**2
  12.     given state @;
  13. }

  14. #my @draw = (for @target[^1000] { stddev $_  }) ;
  15. my @draw = @target[^1000];

  16. my $tmp = open 'rand.svg', :w ;

  17. $tmp.say(
  18.   SVG.serialize: SVG::Plot.new(
  19.       :title( "average = {  @draw.sum  / 1000 }" ),
  20.       :width( 1200 ),
  21.       :height( 600 ),
  22.       :background( '#fffff0' ),
  23.       :colors( 'rgba(0,255,0,0.5)', 'rgba(0,0,255,0.5)' ),
  24.       :label-font-size( 10 ),
  25.       :labels( 1.. 1000 ),
  26.       :values( $@draw ),
  27.   ).plot(:lines)
  28. ) ;

  29. $tmp.close ;
複製代碼







作者: chevylin0802    時間: 2017-6-6 06:56 PM

本帖最後由 chevylin0802 於 2017-6-6 06:59 PM 編輯
weirdococo 發表於 2017-6-6 06:03 PM
先上結果
原始資料:
標準化:


把你手上的結果換成只取百位數
應該就會得到0到9的數字
我請你做的實驗是
最少需要多少次的次數
才能得到0到9的出現次數結果趨近於一致
你會發現,隨機亂數的方式,需要極大量的次數才能出現趨近一致的理論值
但是我講的方式
卻可以只用100次或1000次就能實現
作者: a333221    時間: 2017-6-9 11:19 PM

有沒有達到作弊效果,就驗證而言,要做夠多次的擲骰子,

只要擲的次數越多,得到的結果就會越接近真實的機率值,

驗證的過程是擲的次數越多,得到的結果被視為越可靠,

而非先假定結果是什麼,然後試著在擲一定的次數後要看到想看的結果

除非像民調那樣,用抽樣來估整體,但民調跟骰子好像沒什麼關係 
作者: ren1244    時間: 2017-6-10 11:30 AM

本帖最後由 ren1244 於 2017-6-10 11:31 AM 編輯

如果希望更複雜的比例,這邊提供一個算法


範例:

點數

1

2

3

4

5

6

比例

1.3

1.1

1.4

1.1

1.5

1.9

機率

0.157

0.133

0.169

0.133

0.181

0.229

累進機率

0.157

0.289

0.458

0.59

0.771

1


[attach]119078859[/attach]

參考程式碼:http://codepad.org/iSj00cEC
作者: weirdococo    時間: 2017-6-11 11:22 AM

weirdococo 發表於 2017-6-6 06:03 PM
先上結果
原始資料:
標準化:

我也覺得怪怪的,而且那亂數感覺起來有沒有落在500的感覺,整體偏低的樣子,還有,感覺起來我自己寫的標準化有些問題(或者那亂數有問題),找機會用R跑跑看(雖然還沒有學過)。
作者: weirdococo    時間: 2017-6-11 11:27 AM

ren1244 發表於 2017-6-10 11:30 AM
如果希望更複雜的比例,這邊提供一個算法

好,找機會測試看看,順便一提,我還會想想如何把這個想法(演算)生成不重複了亂數表,那樣說不定會很有用(之前在想說做出一個hash要從頭到尾查詢,如果key都在最後一個就會沒有效率,但是如果我把它改為不重複亂數key查詢,說不定有效率一些)。
作者: volk1979    時間: 2019-3-8 09:32 PM

chevylin0802 發表於 2017-6-6 06:56 PM
把你手上的結果換成只取百位數
應該就會得到0到9的數字
我請你做的實驗是

...

...

以地球引力方面來看,會不會使用真實骰子來擲的話反而是4/5/6出現的現象來的多

1/2/3因骰子製作時骰子被挖除的材質較少




歡迎光臨 伊莉討論區 (http://web01.eyny.com/) Powered by Discuz!