Re: [問卦] 不用函數庫和亂數 寫程式求pi值的方法?

看板Gossiping作者 (松鼠)時間5年前 (2019/04/19 02:27), 編輯推噓140(1422101)
留言245則, 156人參與, 4年前最新討論串3/4 (看更多)
※ 引述《fragmentwing (片翼碎夢)》之銘言: : 小弟程式設計新手 : 看到後面的講義習題要算圓周率 : 如果不用亂數,也不用函數庫的話 : 我自己用了一個在寫之前就覺得很浪費電腦能力的方法 : 在電腦能力處理極限,還沒法精確到小數點後第二位呢 : 鄉民會怎麼用程式求圓周率呢? 這裡提供一種途徑,只用到 C 語言標準函式庫裡頭的以下函式: * fopen / fclose * getc / putc 既然上述說要「浪費電腦能力」,那我們不妨試試這個策略: a. 實作符合 Turing completeness (圖靈完備) 的 Brainfuck 程式語言 [1] 執行環境; b. 撰寫 Brainfuck 程式,使其得以計算圓周率,並用十進位浮點數輸出; 可將 Brainfuck 的執行環境設想為一台機器,擁有一個讀寫頭及無限長的紙帶, 機器會依下列指令進行操作: > : 使讀寫頭在紙帶上前進一格 < : 使讀寫頭在紙帶上後退一格 + : 對目前讀寫頭下的值,進行遞增 1 的運算 - : 對目前讀寫頭下的值,進行遞減 1 的運算 . : 將目前讀寫頭下的值,以對應的字母輸出 , : 將目前讀寫頭下的字母讀入並轉為數字後寫回 [ : 比較目前的值,若不為 0 即前進,若為 0 就略過指令,直到遇上匹配的 ] ] : 比較目前的值,若不為 0,指令要跳回上個出現 [ 的位置 不難發現,作為一個「知易行難」的程式語言,Brainfuck 僅有 8 個指令,其中 2 個是 I/O 動作。作為 Turing machine 的實踐,Brainfuck 對記憶體單元作直接 存取,對應到 C 語言的概念來說,如果 char *p 指向記憶體區塊的話,Brainfuck 語言的 8 個指令可對照為以下 C 等價敘述: Brainfuck C --------- --------- > ++p; < --p; + ++*p; - --*p; . putchar(*p); , *p = getchar(); [ while (*p) { ] } 也就是說,下方的 Brainfuck 程式碼: +++++[-] 對應到 C 語言程式碼為: *p = +5; while (*p != 0) { *p--; } 既然有了指令對照表,我們即可著手建構小型的 Brainfuck 直譯器: (檔名為 bf.c) #include <stdio.h> #include <stdlib.h> static int p[64 * 1024], d[1024 * 1024], r, t, e; int main(int c, char *v[]) { if (c < 2) exit(1); for (FILE *f = fopen(v[1], "r"); f && (c = getc(f)) != EOF; p[r++] = c); for (r = 0; (c = p[r]); r++) { if (c == '>') t++; if (c == '<') t--; if (c == '+') d[t]++; if (c == '-') d[t]--; if (c == '.') putc(d[t], stdout); for (e = 0; c == '[' && !d[t]; r++) { if (p[r] == '[') e++; if ((p[r] == ']') && (e-- == 1)) break; } for (; c == ']' && d[t]; r--) { if (p[r] == ']') e++; if ((p[r] == '[') && (e-- == 1)) break; } } } 回到一開始提到的 Turing completeness,Brainfuck 與其說是程式語言,不如說是 一台理想機器的描述:機器具有無限的儲存 (storage,也就是無限長的紙帶)、運算 (arithmetic,如遞增和遞減)、條件判斷 ([ ] 涉及目前值是否為 0 的判斷) 以及 重複 (repetition,這也是 [ ] 的行為),Brainfuck 這台機器具備上述四項特徵, 是 Turing completeness。依據 Alan Turing 的觀點,這樣的一台機器,即可模擬 人類所能進行的任何計算過程,自然就包含圓周率的計算。 Felix Nawothnig 撰寫出可依據給定位數要求,計算並輸出十進位表示法的 Brainfuck 程式 [2],我略作調整,如下: (檔名為 pi.b) > +++++ +++++ +++++ +++++ +++++ (25 digits) [<+>>>>>>>>++++++++++<<<<<<<-]>+++++[<+++++++++>-]+>>>>>>+[<<+++[>>[-<]<[>]<-]> >[>+>]<[<]>]>[[->>>>+<<<<]>>>+++>-]<[<<<<]<<<<<<<<+[->>>>>>>>>>>>[<+[->>>>+<<<< ]>>>>>]<<<<[>>>>>[<<<<+>>>>-]<<<<<-[<<++++++++++>>-]>>>[<<[<+<<+>>>-]<[>+<-]<++ <<+>>>>>>-]<<[-]<<-<[->>+<-[>>>]>[[<+>-]>+>>]<<<<<]>[-]>+<<<-[>>+<<-]<]<<<<+>>> >>>>>[-]>[<<<+>>>-]<<++++++++++<[->>+<-[>>>]>[[<+>-]>+>>]<<<<<]>[-]>+>[<<+<+>>> -]<<<<+<+>>[-[-[-[-[-[-[-[-[-<->[-<+<->>]]]]]]]]]]<[+++++[<<<++++++++<++++++++> >>>-]<<<<+<->>>>[>+<<<+++++++++<->>>-]<<<<<[>>+<<-]+<[->-<]>[>>.<<<<[+.[-]]>>-] >[>>.<<-]>[-]>[-]>>>[>>[<<<<<<<<+>>>>>>>>-]<<-]]>>[-]<<<[-]<<<<<<<<]++++++++++. 乍看鬼畫符的程式,注意到最後一個字元是 . (將目前讀寫頭下的值,以對應的字母輸出) 編譯 Brainfuck 直譯器並載入圓周率計算程式: $ gcc -o bf bf.c $ ./bf pi.b 在我的電腦 (AMD Ryzen Threadripper 2990WX 32-Core Processor, AMD 重返榮耀!) 搭配 Ubuntu Linux 18.04 LTS,執行時間約為 0.3 秒,ELF 執行檔約佔 6KB 空間。 參考執行輸出如下: 3.141592653589793238462643 若要提高圓周率計算的有效位數,那麼修改 pi.b 的第一行,把 + 指令的數量增加即可。 用雙手駕馭電腦的滋味,真是美妙 :-) [1] brainf*ck: https://esolangs.org/wiki/brainfuck [2] https://copy.sh/brainfuck/prog/yapi.b -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.116.246.163 ※ 文章網址: https://www.ptt.cc/bbs/Gossiping/M.1555612071.A.14C.html

04/19 02:28, 5年前 , 1F
恩恩 昨晚媽祖也是跟我講這個答案
04/19 02:28, 1F

04/19 02:28, 5年前 , 2F
阿伯,早點睡 不要熬夜
04/19 02:28, 2F

04/19 02:29, 5年前 , 3F
幹 不要回這種好嗎 我還不想睡覺
04/19 02:29, 3F

04/19 02:29, 5年前 , 4F
今天還有一萬多人 都被柴員了嗎
04/19 02:29, 4F

04/19 02:30, 5年前 , 5F
先推再看
04/19 02:30, 5F

04/19 02:30, 5年前 , 6F
先推不然別人以為我看不懂
04/19 02:30, 6F

04/19 02:31, 5年前 , 7F
先推
04/19 02:31, 7F

04/19 02:33, 5年前 , 8F
+<>< +<><
04/19 02:33, 8F

04/19 02:33, 5年前 , 9F
jserv 先給推
04/19 02:33, 9F

04/19 02:33, 5年前 , 10F
松鼠竟然也投奔真香世界了
04/19 02:33, 10F

04/19 02:34, 5年前 , 11F
google pi ten thousand digits
04/19 02:34, 11F

04/19 02:35, 5年前 , 12F
cool
04/19 02:35, 12F

04/19 02:39, 5年前 , 13F
半夜大神出巡,推。
04/19 02:39, 13F

04/19 02:42, 5年前 , 14F
AMD 重返榮耀!
04/19 02:42, 14F

04/19 02:42, 5年前 , 15F
...為什麼要這樣子算
04/19 02:42, 15F

04/19 02:43, 5年前 , 16F
@q14721472, 回歸初心 (?)
04/19 02:43, 16F

04/19 02:45, 5年前 , 17F
......
04/19 02:45, 17F

04/19 02:45, 5年前 , 18F
跪著推
04/19 02:45, 18F

04/19 02:46, 5年前 , 19F
04/19 02:46, 19F

04/19 02:47, 5年前 , 20F
@a3831038, 那我忘了附上「真香警告」
04/19 02:47, 20F

04/19 02:50, 5年前 , 21F
第一頁要標註「Brainfuck不是Pornhub的新分類」(嗶!)
04/19 02:50, 21F

04/19 02:51, 5年前 , 22F
第一次前20
04/19 02:51, 22F

04/19 02:54, 5年前 , 23F
04/19 02:54, 23F

04/19 02:55, 5年前 , 24F
半夜睡不著覺
04/19 02:55, 24F

04/19 02:56, 5年前 , 25F
@lovesooman, 其實這篇沒寫完,數學原理還沒探討,我正在
04/19 02:56, 25F

04/19 02:56, 5年前 , 26F
排版,作為新教材。從 Turing 機器到征服圓周率運算
04/19 02:56, 26F

04/19 02:57, 5年前 , 27F
講中文好嗎
04/19 02:57, 27F

04/19 02:58, 5年前 , 28F
@newland, 夜睡不著覺,把 pi 哼成 C 程式
04/19 02:58, 28F

04/19 03:01, 5年前 , 29F
朝聖推
04/19 03:01, 29F

04/19 03:01, 5年前 , 30F
04/19 03:01, 30F

04/19 03:03, 5年前 , 31F
04/19 03:03, 31F

04/19 03:03, 5年前 , 32F
@jj1379746, 也是可改用 BF 來講
04/19 03:03, 32F

04/19 03:04, 5年前 , 33F
厲害
04/19 03:04, 33F

04/19 03:05, 5年前 , 34F
04/19 03:05, 34F

04/19 03:05, 5年前 , 35F
04/19 03:05, 35F

04/19 03:07, 5年前 , 36F
04/19 03:07, 36F

04/19 03:10, 5年前 , 37F
ob'_'ov AMD讚
04/19 03:10, 37F

04/19 03:10, 5年前 , 38F
我老闆問我為啥要跪著上班
04/19 03:10, 38F

04/19 03:12, 5年前 , 39F
恩...略懂
04/19 03:12, 39F
還有 166 則推文
04/19 16:19, 5年前 , 206F
朝聖推
04/19 16:19, 206F

04/19 17:24, 5年前 , 207F
.... 太神啦
04/19 17:24, 207F

04/19 17:31, 5年前 , 208F
說中文
04/19 17:31, 208F

04/19 17:35, 5年前 , 209F
大哥,請講地球話,謝謝
04/19 17:35, 209F

04/19 19:03, 5年前 , 210F
朝聖 XDDDDDDD
04/19 19:03, 210F

04/19 19:08, 5年前 , 211F
ubuntu給推
04/19 19:08, 211F

04/19 20:24, 5年前 , 212F
跪推
04/19 20:24, 212F

04/19 20:48, 5年前 , 213F
朝聖
04/19 20:48, 213F

04/19 20:54, 5年前 , 214F
我都看了些什麼
04/19 20:54, 214F

04/19 22:16, 5年前 , 215F
直譯器是不是少了一個 BF operator ","
04/19 22:16, 215F

04/19 23:17, 5年前 , 216F
朝聖
04/19 23:17, 216F

04/20 00:57, 5年前 , 217F
04/20 00:57, 217F

04/20 01:40, 5年前 , 218F
百推內
04/20 01:40, 218F

04/20 02:17, 5年前 , 219F
推成大神
04/20 02:17, 219F

04/20 06:10, 5年前 , 220F
未來寫程式可能跟藝術一樣 沒有選語言的限制
04/20 06:10, 220F

04/20 09:18, 5年前 , 221F
@BabySatan, 是的,輸入的指令故意忽略,為了省行數
04/20 09:18, 221F

04/20 09:18, 5年前 , 222F
@wario2014, 在地球上能夠被人理解的語言算地球話吧?BF是
04/20 09:18, 222F

04/20 09:19, 5年前 , 223F
@eric21489, 望您牽成,再推幾把
04/20 09:19, 223F

04/20 09:19, 5年前 , 224F
@thaleschou, 你看到活生生的圖靈機
04/20 09:19, 224F

04/20 09:20, 5年前 , 225F
@wzshi, 中文程式語言好幾套,包含台灣人做的丙正正(C++的
04/20 09:20, 225F

04/20 09:21, 5年前 , 226F
中文版本,用中文保留字和允許中文符號)
04/20 09:21, 226F

04/20 09:25, 5年前 , 227F
上述的pi.b運作原理是1995年BBP公式的變形,儘管BF沒內建
04/20 09:25, 227F

04/20 09:26, 5年前 , 228F
豐富數學運算,但由於其Turing完備本質,所以我們仍可將BBP
04/20 09:26, 228F

04/20 09:27, 5年前 , 229F
轉換為等價BF操作,於是圓周率的計算類似長整數乘法,展開
04/20 09:27, 229F

04/20 09:28, 5年前 , 230F
為一系列的指標和迴圈操作
04/20 09:28, 230F

04/20 09:55, 5年前 , 231F
U文 在fb看到跑來推文
04/20 09:55, 231F

04/20 10:16, 5年前 , 232F
朝聖推
04/20 10:16, 232F

04/20 16:27, 5年前 , 233F
不免會有人質疑上述手法「有什麼用?」用途總是人們找出的
04/20 16:27, 233F

04/20 16:28, 5年前 , 234F
比方說,這手法對於程式混淆器有一定助益,成就write-only
04/20 16:28, 234F

04/20 16:29, 5年前 , 235F
code,要從Brainf*ck一類程式碼反推最初高階程式流程相當難
04/20 16:29, 235F

04/20 16:29, 5年前 , 236F
04/20 16:29, 236F

04/20 22:50, 5年前 , 237F
j教授又下凡了 跪
04/20 22:50, 237F

04/22 05:59, 5年前 , 238F
居然被大神回啦 以後開始學C回來看看
04/22 05:59, 238F

04/22 08:40, 5年前 , 239F
04/22 08:40, 239F

04/22 10:19, 5年前 , 240F
@fragmentwing, 你要多推坑,讓我可以置入性行銷C語言
04/22 10:19, 240F

05/06 12:52, 5年前 , 241F
朝聖
05/06 12:52, 241F

09/12 15:04, 4年前 , 242F
希望電蝦板的WarGame723可以看到...
09/12 15:04, 242F

09/12 15:04, 4年前 , 243F
2990WX算圓周率!!
09/12 15:04, 243F

09/12 15:04, 4年前 , 244F
@jserv
09/12 15:04, 244F

04/26 16:54, 4年前 , 245F
04/26 16:54, 245F
文章代碼(AID): #1SkC6d5C (Gossiping)
討論串 (同標題文章)
文章代碼(AID): #1SkC6d5C (Gossiping)