# Stata程序：最大公约数和最小公倍数

Stata连享会   主页 || 视频 || 推文 || 知乎

New！ `lianxh` 命令发布了：

`. ssc install lianxh`

`. help lianxh`

⛳ Stata 系列推文：

## 2. 算法原理

### 2.1 最大公约数

``````求 (319, 377)

∵ 319 ÷ 377 = 0 (余 319)
∴ (319, 377) = (377, 319)

∵ 377 ÷ 319 = 1 (余 58)
∴ (377, 319) = (319, 58)

∵ 319 ÷ 58 = 5 (余 29)
∴ (319, 58) = (58, 29)

∵ 58 ÷ 29 = 2 (余 0)
∴ (58, 29) = 29

∴ (319, 377) = 29
``````

### 2.2 最小公倍数

``````求 [18, 20]

[18, 20] = 18 × 20 ÷ (18, 20) = 18 × 20 ÷ 2 = 180
``````

## 3. Stata 实现

### 3.1 基础代码

#### 3.1.1 公约数：1 个或 2 个自然数的最大公约数

• 若为 1 个，则最大公约数是其本身；
• 若为 2 个，则通过 `while` 循环命令和 `mod` 取余命令实现「辗转相除法」计算最大公约数；

``````* Greatest Common Denominator (GCD) of 2 integers
cap program drop gcd
program define gcd
if "`2'" == "" {
dis `1'
}
else {
while `2' {
local temp2 = `2'
local 2 = mod(`1',`2')
local 1 = `temp2'
}
dis `1'
}
end

gcd 100
gcd 5 10
``````

``````. gcd 100
100
. gcd 5 10
5
``````

#### 3.1.2 存储最大公约数的计算结果

``````* Greatest Common Denominator (GCD) of 2 integers
cap program drop gcd
program define gcd, rclass
if "`2'" == "" {
return scalar gcd = `1'
}
else {
while `2' {
local temp2 = `2'
local 2 = mod(`1',`2')
local 1 = `temp2'
}
return scalar gcd = `1'
}
end

gcd 100
dis r(gcd)

gcd 5 10
dis r(gcd)
``````

``````. gcd 100
. dis r(gcd)
100

. gcd 5 10
. dis r(gcd)
5
``````

#### 3.1.3 公倍数：1 个或 2 个自然数的最小公倍数

``````* Least Common Multiple (LCM) of 2 integers
cap program drop lcm
program define lcm, rclass
if "`2'" == "" {
return scalar lcm = `1'
}
else {
gcd `1' `2'
return scalar lcm = `1' * `2' / r(gcd)
}
end

lcm 100
dis r(lcm)

lcm 5 10
dis r(lcm)
``````
``````. lcm 100
. dis r(lcm)
100

. lcm 5 10
. dis r(lcm)
10
``````

#### 3.1.4 多个自然数的最大公约数和最小公倍数

``````* GCD of arbitrarily long list of integers
cap program drop gcdm
program define gcdm, rclass
clear results
foreach i of local 0 {
gcd `i' `r(gcd)'
}
return scalar gcd = r(gcd)
di "`r(gcd)'"
end

* LCM of arbitrarily long list of integers
cap program drop lcmm
program define lcmm, rclass
clear results
foreach i of local 0 {
lcm `i' `r(lcm)'
}
return scalar lcm = r(lcm)
di "`r(lcm)'"
end

gcdm 5 10 15
lcmm 5 10 15
``````
``````. gcdm 5 10 15
5

. lcmm 5 10 15
30
``````

#### 3.2.1 若用户输入的参数不是正整数，报错并提示

``````* GCD of arbitrarily long list of integers

* Greatest Common Denominator (GCD) of long list of integers
capture program drop gcdm
program define gcdm,rclass
clear results
capture syntax anything(name=n)
if _rc{  // 用户忘了输入数字
dis as error "You must enter positive integers"
exit
}
tokenize "`n'"
local j = 1
while "``j''" !=""{     // `j' 表示房间号；``j'' 表示房间中的内容
local k = ``j''       // 注意暂元的引用方式
capture confirm integer number `k' // 用户输入了非整数或文字
if _rc{
dis as error "You must enter positive integers"
exit
}
if `k'<= 0{  // 用户输入了负数
dis as error "You must enter positive integers"
exit
}

gcd `k' `r(gcd)'
local j = `j' + 1
}
return scalar gcdm = r(gcd)

end

gcdm
gcdm 10.5
gcdm -10
gcdm 100 200 50
dis r(gcdm)
``````
``````. gcdm
You must enter positive integers

. gcdm 10.5
You must enter positive integers

. gcdm -10
You must enter positive integers

. gcdm 100 200 50

. dis r(gcdm)
50
``````

#### 3.2.2 产生新变量

``````* Greatest Common Denominator (GCD) of 2 integers
capture program drop gcd
program define gcd,rclass
if "`2'" == "" {
return scalar gcd =`1'
}

else {
while `2' {
local temp2 = `2'
local 2 = mod(`1',`2')
local 1 = `temp2'
}

return scalar gcd = `1'
}

end

* Greatest Common Denominator (GCD) of 2 integers
capture program drop gcdm
program define gcdm,rclass
clear results
capture syntax anything(name=n)[,GENerate(string) replace]
if _rc{  // 用户忘了输入数字
dis as error "You must enter positive integers"
exit
}
if "`generate'" != ""{
if "`replace'" != "" {
capture drop `generate'
}
gen `generate' = .

}

tokenize "`n'"
local j = 1
while "``j''" !=""{     // `j' 表示房间号；``j'' 表示房间中的内容
local k = ``j''       // 注意暂元的引用方式
capture confirm integer number `k' // 用户输入了非整数或文字
if _rc{
dis as error "You must enter positive integers"
exit
}
if `k'<= 0{  // 用户输入了负数
dis as error "You must enter positive integers"
exit
}

gcd `k' `r(gcd)'
local j = `j' + 1

}
if "`generate'" != ""{
replace `generate'= r(gcd)
}
return scalar gcdm = r(gcd)

//	di r(gcdm)

//	di "`r(gcdm)'"

end

clear
set obs 3
gen x = 1
gen mm=1
gcdm 100 200 50 30 20 60 80 60, gen(mm) replace
dis r(gcdm)
list if _n<=1

gcdm 100 200 50,gen(mm) replace
dis r(gcdm)
list if _n<=1
``````
``````. gcdm 100 200 50 30 20 60 80 60, gen(mm) replace
(3 missing values generated)

. dis r(gcdm)
10

. list if _n<=1

+--------+
| x   mm |
|--------|
1. | 1   10 |
+--------+

.
. gcdm 100 200 50,gen(mm) replace
(3 missing values generated)

. dis r(gcdm)
50

. list if _n<=1

+--------+
| x   mm |
|--------|
1. | 1   50 |
+--------+
``````

`capture syntax anything(name=n)` 后选项 `[,GENerate(string) replace]` 的添加，允许用户使用命令 `generate` 生成新变量并存储计算结果，若使用 `generate replace` 命令则会替换原有的变量。

## 4. 帮助文档

``````{smcl}
{* 9 Dec 2020}{...}
{hline}
help for {hi:gcdm}
{hline}

{title:Title}

{p 4 4 2}
{bf:gcdm} —— Compute the Greatest Common Denominator (GCD) of Positive Integers

{title:Syntax}

{p 4 4 2}
{cmdab:gcdm} {anything},
[
{cmdab:g:enerate}{cmd:(}varname{cmd:)} {cmd:replace}
]

{title:Description}

{p 4 4 2}
{cmd:gcdm} makes it easy for users to compute the greatest common denominator (GCD) of positive integers
and the result is stored in r(gcdm).

{title:Options}
{phang}
{cmdab:g:enerate(}{it:varname}{cmd:)} Specifies the name for the greatest common denominator (GCD) variable.
{p_end}
{phang}
{cmd:replace} Specifies that an existing variable is to be overwritten with parameter draws.
{p_end}

{title:Examples}

{p 4 4 2} *- Calculate the greatest common denominator (GCD) of 5 10 15 30. {p_end}
{p 4 4 2}{inp:.} {stata `"gcdm 5 10 15 30"'}{p_end}
{p 4 4 2}{inp:.} {stata `"dis r(gcdm)"'}{p_end}

{p 4 4 2} *- Calculate the greatest common denominator (GCD) of 5 10 15 30 and generate a new variable to store it {p_end}
{p 4 4 2}{inp:.} {stata `"clear"'}{p_end}
{p 4 4 2}{inp:.} {stata `"set obs 3"'}{p_end}
{p 4 4 2}{inp:.} {stata `"gen x = 1"'}{p_end}
{p 4 4 2}{inp:.} {stata `"gcdm 5 10 15 30,gen(gcd_result) replace"'}{p_end}

{title:Author}

{p 4 4 2}
{cmd:Chaonan,Feng}{break}
School of Economics and Management, Beihang University.{break}
E-mail: {browse "mailto:fengcnhpy@126.com":fengcnhpy@126.com}. {break}

``````

## 6. 参考资料

• Computing greatest common denominators and least common multiples in Stata -Link-
• Manipulating locals via macro lists -Link-

## 7. 相关推文

Note：产生如下推文列表的 Stata 命令为：
`lianxh 程序, m`

`ssc install lianxh, replace`

## 相关课程

### 最新课程-直播课

• Note: 部分课程的资料，PPT 等可以前往 连享会-直播课 主页查看，下载。

### 关于我们

• Stata连享会 由中山大学连玉君老师团队创办，定期分享实证分析经验。
• 连享会-主页知乎专栏，400+ 推文，实证分析不再抓狂。直播间 有很多视频课程，可以随时观看。
• 公众号关键词搜索/回复 功能已经上线。大家可以在公众号左下角点击键盘图标，输入简要关键词，以便快速呈现历史推文，获取工具软件和数据下载。常见关键词：`课程, 直播, 视频, 客服, 模型设定, 研究设计, stata, plus, 绘图, 编程, 面板, 论文重现, 可视化, RDD, DID, PSM, 合成控制法`

✏ 连享会学习群-常见问题解答汇总：
https://gitee.com/arlionn/WD

New！ `lianxh` 命令发布了：

`. ssc install lianxh`

`. help lianxh`