Mata:Mata编程语句

Mata:Mata编程语句

在连玉君老师的帮助下终于找到了这本书的电子版,之前看的是从图书馆借的纸质版(当然也是我推荐图书馆购买的)。点击即可下载这本书:The_Mata_Book.pdf

所以再帮连玉君老师做个广告:连玉君 | 简书

Mata程序的结构

一个程序就是一段代码块,下面是一些示例:

函数speed_of_light()没有任何参数传入,返回一个值:

Stata
1
2
3
4
real scalar speed_of_light()
{
return(299792458 /* m/s */)
}

使用:

Stata
1
2
3
4
5
6
7
8
mata:
mata clear
real scalar speed_of_light()
{
return(299792458 /* m/s */)
}
speed_of_light()
end

函数show()传入参数之后什么也不返回,但是会打印出来一些东西:

Stata
1
2
3
4
void show(real scalar a)
{
printf("a = %f\n", a)
}

使用:

Stata
1
2
3
4
5
6
7
8
mata:
mata clear
void show(real scalar a)
{
printf("a = %f\n", a)
}
show(12)
end

下面的函数n_choose_k()和函数nfactorial_over_kfactorial()则具有实际数据意义了,他们接收参数并返回结果。

Stata
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
real scalar n_choose_k(real scalar n, real scalar k)
{
return(n - k > k ?
nfactorial_over_kfactorial(n, n - k) /
nfactorial_over_kfactorial(k, 1)
:
nfactorial_over_kfactorial(n, k) /
nfactorial_over_kfactorial(n - k, 1)
)
}

real scalar nfactorial_over_kfactorial(real scalar n, real scalar k)
{
real scalar result, i
if (n < 0 | n > 1.0x+35 | n != trunc(n)) return(.)
if (k < 0 | k > 1.0x+35 | k != trunc(k)) return(.)
result = 1
for(i = n; i > k; --i) result = result * i
return(result)
}

正如上篇博客中已经说明的一样:

$$
\begin{align}
nfactorial\_over\_kfactorial(n, k) & = \frac{n!}{k!} \
n\_choose\_k(n, k) = C^k_n & = \frac{n!}{(n-k)!k!}
\end{align}
$$

相信从上面的示例中你已经发现了Mata程序的一般结构了,如果没有返回值,函数会被声明为void。虽然你可以省略函数类型的声明,但是本书的作者不建议这么做,因为这会增加错误的概率和让程序编译的更慢。

程序体

在Mata中有九种语句:

  1. 条件语句:
Stata
1
if (expr) ... else ...
  1. 循环语句:
Stata
1
2
3
4
5
for (expr; expr; expr) ...
while (expr) ...
do ... while (expr)
continue (继续下一个循环迭代)
break (跳出循环)
  1. Go-to语句(在翻译Fotran程序的时候非常有用):
Stata
1
goto stmt
  1. 退出与返回值语句:
Stata
1
return and return(expr)
  1. 赋值、子程序调用语句:
Stata
1
expr

表达式

在下一章我们将会更加深入的讲解表达式,一些常见的表达式示例:

Stata
1
2
3
i = i + 1
y = mycn(x)
mysubroutine(a, b)

还有一种你看起来不像表达式的表达式,但它就是表达式:返回void的表达式。

需要注意的是,数学表达式和逻辑表达式虽然运算方法不一样,但是返回的结果的类型是一样的,这就意味着你可能把数学表达式和逻辑表达式一起使用。例如,考虑三个数值变量a、b和c,它们中有几个是负数?,答案就是(a < 0) + (b < 0) + (c < 0)。

数学表达式也可以被当作逻辑表达式来使用,规则就是如果表达式返回的不是0就是1。数学表达式和逻辑表达式等同是Mata语言的第一个特性。

Mata语言的第二个特性就是,=表示赋值而==表示逻辑判断。

所以你一定要注意不要把:

Stata
1
if (x == 2) ...

打成了:

Stata
1
if (x = 2) ...

因为第二个式子并不会返回错误,它会把x赋值为2,同事x = 2这个表达式会被视为true。

Mata的最后一个特性就是++--运算符了,观察下面的两个式子:

  • z = v[i++] + x
  • z = v[++i] + x

v[i++]表示获取v[i]然后把i增加1;
v[++i]表示先增加i然后再获取v[i]。

例如,如果在语句执行前i为2,那么:
v[i++]是v[2],而v[++i]是v[3]。

条件语句

这里没什么值得啰嗦的。

循环语句

Mata中有三种循环结构:

  1. for;
  2. while;
  3. do … while

例如求$\sqrt{2}$:

Stata
1
2
3
4
5
6
mata:
mata clear
x = 1
while (abs(x^2 - 2) > 1e-8) x = x - (x^2 - 2)/(2 * x)
x
end

运行结果:

Stata
1
2
3
4
5
6
7
8
9
10
11
12
13
. mata:
------------------------------------------------- mata (type end to exit) ----------------------
: mata clear

: x = 1

: while (abs(x^2 - 2) > 1e-8) x = x - (x^2 - 2)/(2 * x)

: x
1.414213562

: end
------------------------------------------------------------------------------------------------

而如果使用for语句,下面的三种形式都是可以的:

Stata
1
2
3
for (x = 1; abs(x^2 - 2) > 1e-8;) x = x - (x^2 - 2)/(2*x)
for (x = 1; abs(x^2 - 2) > 1e-8; x = x - (x^2 - 2)/(2*x)){}
for (x = 1; abs(x^2 - 2) > 1e-8; x = x - (x^2 - 2)/(2*x));

例如:

Stata
1
2
3
4
. mata: for (x = 1; abs(x^2 - 2) > 1e-8; x = x - (x^2 - 2)/(2*x));

. mata: x
1.414213562

而对于continuebreakcontinue表示循环剩下的部分将被跳过,但是循环还会继续,而break表示跳出循环。

GOTO语句在翻译Fortran语句时非常有用,例如对于下面的Fortran语句:

1
2
3
4
5
    A = 4.0e0/3.0e0
10 B = A - 1.0e0
C = B + B + B
EPS = DABS(C - 1.0e0)
if (EPS.EQ.0.0e0) GOTO 10

翻译成Mata语句:

Stata
1
2
3
4
5
      A = 4.0e0/3.0e0
s10: B = A - 1.0e0
C = B + B + B
EPS = abs(C - 1.0e0)
if (EPS == 0.0e0) goto s10

return

这里只有一点需要额外知道的,就是return可以用在程序中以提前结束程序。

# Mata

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×