前往
大廳
主題

【指令】從MC學數學系列① ─ MC的運算規則、利用後序運算解析複雜的算數指令

雪色 | 2022-02-20 11:32:30 | 巴幣 1000 | 人氣 200

這裡又是好久不見的雪色
拖更好像已經是我的習慣了,完蛋(X
為了治療自己的拖更症,讓自己開始往奇怪的方向發展中

此為一系列,預計約莫1~2個月會發表一篇文章,
主要是引導國高中生、對於Minecraft指令有興趣並想深入研究的學生參考,
從中可以學習一些應用數學的計算方式、計算幾何與一些簡單的演算法概念

( ⚠ 本篇文章難度很高,請至少熟悉以下的先備知識後會比較容易閱讀 )
execute, scoreboard, data指令
至少具備國中程度的數學能力 ─ 未知數與方程式


在此篇文章能學到什麼 ?

一、統整Minecraft的基礎計算規則與操作
二、利用後序運算解析數學式
三、理解單變數函數與雙變數函數



目錄

一、算術運算(Arithmetic Operation)
二、比較運算(Comparison Operation)
三、後序式(Suffix Expression)
四、綜合運用
五、次篇預告



一、算術運算(Arithmetic Operation)

1. 記分板運算(Scoreboard Operation)

    記分板(scoreboard),是一個在Minecraft中非常便於進行計算操作的工具,
    記分板可以儲存 [-2147483648, 2147483647]=[-2^31, 2^31-1] 的值
    在scoreboard players operation 中,一共有以下幾種的操作方式
Op 表達式 計算方式說明
+= a=a+b 使a加上b的值
-= a=a-b 使a減去b的值
*= a=a*a 使a乘上b的值
/= a=a/b 使a除去b的值
%= a=a%b 使a模去b的值 (≡ a mod b),又或稱為 使a為a除b的餘數
= a=b 使a為b的值
< a=min(a,b) 使a為a和b的最小值
> a=max(a,b) 使a為a和b的最大值
>< swap(a,b) 交換a和b的值,唯一個雙向操作(bi-operation)

    舉例來說,執行 /scoreboard players operation #a var >< #b var
    會將 #a 的 var 與 #b 的 var 進行交換(swap)
    
    我們在後篇會將這些計算操作簡寫成冒號右側的映射(mapping)形式,如 swap(#a[var], #b[var])

2. 小數/浮點數運算(Floating Number Operation)
這將會在後續幾篇中進行詳細講解,包含實作過程與可以應用的操作方式
(先賣個關子,敬請期待(X


二、比較運算(Comparison Operation)
  • 數值區間(range)的格式:
區間 條件式 比較方式說明
u [u,u] value==u 若值等於u
..u (,u] value<=u 若值小於等於u
u.. [u,) value>=u 若值大於等於u
v..u [v,u] v<=value<=u 若值大於等、於v小於等於u

以下我們會將數值區間的變數記做 [r]

1. 實體選擇器(Selector)
selector中有提供可以查詢scoreboard數值與區間的方式
@#[score={obj=[r]}]:若目標的obj分數介於數值區間 [r] 之間

2. execute if score
相比於selector可以用來比較變數區間的情況,其額外提供了以下幾種比較方式:
< a<b 若a小於b
<= a<=b 若a小於等於b
= a==b 若a等於b
> a>b 若a大於b
>= a>=b 若a大於等於b
matches [r] a∈[r] 若值介於數值區間 [r] 之間



三、後序式(Suffix Expression)

有時候觀察一個數學式子,像是一個 之類的式子都要觀察老半天,
或是看到別人寫的計算數學的函數又不知道該怎麼樣快速看的話,
我們在這裡會提供一個可以快速解析的方式

在這裡先提及一個數學式結構的概念:
表達式 Expression 格式 範例
前序 prefix + a b * + 2 3 7
中序 infix a + b ( 2 + 3 ) * 7
後序 postfix a b + 2 3 + 7 *

中序式是我們一般解數學題目時會使用的方式,
而轉成後序式可以讓電腦更方便計算,也不用考慮到括弧的問題

(若對此表達式有興趣者,可以查閱網路進一步了解)
(此概念在學習程式的「資料結構」部分時會再提及到一次)

轉換中序式 為 後序式(Infix Expression to Postfix Expression)

假設現有一式:
首先步驟是將其攤平:
後續轉換的步驟是從左往右解析,而轉換後的後序式會是這樣:
我們可以將其依序解析:
在這裡要特別注意根號(√)是一個單變數函式(一元運算),他只會用掉一個數

如果不是很知道該怎麼轉換的可以利用這個線上轉換器來輔助:


知道了後序式之後能做什麼?


當然就是直接寫出指令了,還能做甚麼(?
如果還不是很了解的話,可以把「後序運算的轉換過程」看成是一個「計算流程」,
每當遇到一個運算符(Operator)時就會進行一次計算,
在這裡要如何節省變數用量就會變成很重要的一環了

用範例來看,已知的參數有 (x, a, b, c),在這裡我們會需要加開兩個變數 (k, p):
k = b
k *= b          // k == b^2
p = a
p *= 4          // p == 4a
p *= c          // p == 4ac
k -= p          // k == b^2-4ac
k = sqrt(k)  // k == sqrt(b^2-4ac)
k -= b          // k == sqrt(b^2-4ac)-b
p = a
p *= 2          // p == 2a
k /= p          // k == [sqrt(b^2-4ac)-b]/2a
p = x
p -= k          // p == x-[sqrt(b^2-4ac)-b]/2a

return p as result
(我們有稍微調動計算順序,這麼做主要是為了節省變數用量)

可以觀察我們的計算順序同樣是:* * * - - √ * / -,與後序運算的運算符是相同的,
而解析原本數學式的方式則是像//右側內容一樣來解析,
將此計算流程再寫成指令的話,則可以很輕鬆的實現計算數學式的效果
通常不會特地轉成後序來看,但如果是一個計算量非常大的式子用此方式分析會很快


四、綜合運用

我們可以嘗試將上述的 算術運算 比較運算 的概念給綜合起來,
這就是最基礎程式計算與比較的邏輯
a = 1
b = 4

if ( a > b )
    swap(a, b)

if ( a <= b )
    a = a + sqrt(b)

// a == 1 + 2 == 3

如果換成用Minecraft的指令來寫,則可以寫出類似這樣子的指令:
scoreboard players set a var 1
scoreboard players set b var 4

execute if score a var > b var run scoreboard players operation a var >< b var
execute unless score a var  > b var run function namespace:sqrt_b

execute unless score a var  > b var run scoreboard players operation a var += b var

相比於用Minecraft指令來看,用這種簡單的 虛擬碼(pseudo code) 來表達計算、程式過程會較易讀,
因此接下來的概念會以此作為前導概念進行延伸,大多數的情況都會使用這種虛擬碼的方式來表達


五、次篇預告

此篇主要的功能是作為引導的作用,簡單概述Minecraft裡既有的計算操作方式,
並作為銜接後續文章的前導文之一。

在下一篇,我們會深入討論:函式(Function)的概念與小數運算的實作方式



我們會陸續將這些文章統合起來,並整理到一個平台上(預計是HackMD),
如果有人對於此系列有興趣和想法的也歡迎找我一起來合力撰寫這個系列!因為內容實在非常多(X
然後如果有什麼問題也都可以在下面留言和私我!(不過我可能要到晚上或是隔天才會回訊)


創作回應

追蹤 創作集

作者相關創作

更多創作