Shell 數(shù)值運(yùn)算

2018-10-26 16:48 更新

前言

從本文開始,打算結(jié)合平時(shí)積累和進(jìn)一步實(shí)踐,通過一些范例來介紹Shell編程。因?yàn)榉独軌蚪o人以學(xué)有所用的感覺,而且給人以動(dòng)手實(shí)踐的機(jī)會(huì),從而激發(fā)人的學(xué)習(xí)熱情。

考慮到易讀性,這些范例將非常簡(jiǎn)單,但是實(shí)用,希望它們能夠成為我們解決日常問題的參照物或者是“茶余飯后”的小點(diǎn)心,當(dāng)然這些“點(diǎn)心”肯定還有值得探討、優(yōu)化的地方。

更復(fù)雜有趣的例子請(qǐng)參考 Advanced Bash-Scripting Guide (一本深入學(xué)習(xí) Shell 腳本藝術(shù)的書籍)。

該系列概要:

  • 目的:享受用 Shell 解決問題的樂趣;和朋友們一起交流和探討。
  • 計(jì)劃:先零散地寫些東西,之后再不斷補(bǔ)充,最后整理成冊(cè)。
  • 讀者:熟悉 Linux 基本知識(shí),如文件系統(tǒng)結(jié)構(gòu)、常用命令行工具、Shell 編程基礎(chǔ)等。
  • 建議:看范例時(shí),可參考《Shell基礎(chǔ)十二篇》《Shell十三問》。
  • 環(huán)境:如沒特別說明,該系列使用的 Shell 將特指 Bash,版本在 3.1.17 以上。
  • 說明:該系列不是依據(jù) Shell 語法組織,而是面向某些潛在的操作對(duì)象和操作本身,它們反應(yīng)了現(xiàn)實(shí)應(yīng)用。當(dāng)然,在這個(gè)過程中肯定會(huì)涉及到 Shell 的語法。

這一篇打算討論一下 Shell 編程中的基本數(shù)值運(yùn)算,這類運(yùn)算包括:

  • 數(shù)值(包括整數(shù)和浮點(diǎn)數(shù))間的加、減、乘、除、求冪、求模等
  • 產(chǎn)生指定范圍的隨機(jī)數(shù)
  • 產(chǎn)生指定范圍的數(shù)列

Shell 本身可以做整數(shù)運(yùn)算,復(fù)雜一些的運(yùn)算要通過外部命令實(shí)現(xiàn),比如 exprbc,awk 等。另外,可通過 RANDOM 環(huán)境變量產(chǎn)生一個(gè)從 0 到 32767 的隨機(jī)數(shù),一些外部工具,比如 awk 可以通過 rand() 函數(shù)產(chǎn)生隨機(jī)數(shù)。而 seq 命令可以用來產(chǎn)生一個(gè)數(shù)列。下面對(duì)它們分別進(jìn)行介紹。

整數(shù)運(yùn)算

范例:對(duì)某個(gè)數(shù)加 1

$ i=0;
$ ((i++))
$ echo $i
1

$ let i++
$ echo $i
2

$ expr $i + 1
3
$ echo $i
2

$ echo $i 1 | awk '{printf $1+$2}'
3

說明: expr 之后的 $i,+,1 之間有空格分開。如果進(jìn)行乘法運(yùn)算,需要對(duì)運(yùn)算符進(jìn)行轉(zhuǎn)義,否則 Shell 會(huì)把乘號(hào)解釋為通配符,導(dǎo)致語法錯(cuò)誤; awk 后面的 $1$2 分別指 $i 和 1,即從左往右的第 1 個(gè)和第 2 個(gè)數(shù)。

用 Shell 的內(nèi)置命令查看各個(gè)命令的類型如下:

$ type type
type is a shell builtin
$ type let
let is a shell builtin
$ type expr
expr is hashed (/usr/bin/expr)
$ type bc
bc is hashed (/usr/bin/bc)
$ type awk
awk is /usr/bin/awk

從上述演示可看出: let 是 Shell 內(nèi)置命令,其他幾個(gè)是外部命令,都在 /usr/bin 目錄下。而 exprbc 因?yàn)閯傆眠^,已經(jīng)加載在內(nèi)存的 hash 表中。這將有利于我們理解在上一章介紹的腳本多種執(zhí)行方法背后的原理。

說明:如果要查看不同命令的幫助,對(duì)于 lettype 等 Shell 內(nèi)置命令,可以通過 Shell 的一個(gè)內(nèi)置命令 help 來查看相關(guān)幫助,而一些外部命令可以通過 Shell 的一個(gè)外部命令 man 來查看幫助,用法諸如 help letman expr 等。

范例:從 1 加到某個(gè)數(shù)

#!/bin/bash
# calc.sh

i=0;
while [ $i -lt 10000 ]
do
    ((i++))
done
echo $i

說明:這里通過 while [ 條件表達(dá)式 ]; do .... done 循環(huán)來實(shí)現(xiàn)。-lt 是小于號(hào) <,具體見 test 命令的用法:man test。

如何執(zhí)行該腳本?

辦法一:直接把腳本文件當(dāng)成子 Shell (Bash)的一個(gè)參數(shù)傳入

$ bash calc.sh
$ type bash
bash is hashed (/bin/bash)

辦法二:是通過 bash 的內(nèi)置命令 .source 執(zhí)行

$ . ./calc.sh

$ source ./calc.sh
$ type .
. is a shell builtin
$ type source
source is a shell builtin

辦法三:是修改文件為可執(zhí)行,直接在當(dāng)前 Shell 下執(zhí)行

$ chmod ./calc.sh
$ ./calc.sh

下面,逐一演示用其他方法計(jì)算變量加一,即把 ((i++)) 行替換成下面的某一個(gè):

let i++;

i=$(expr $i + 1)

i=$(echo $i+1|bc)

i=$(echo "$i 1" | awk '{printf $1+$2;}')

比較計(jì)算時(shí)間如下:

$ time calc.sh
10000

real    0m1.319s
user    0m1.056s
sys     0m0.036s
$ time calc_let.sh
10000

real    0m1.426s
user    0m1.176s
sys     0m0.032s
$  time calc_expr.sh
1000

real    0m27.425s
user    0m5.060s
sys     0m14.177s
$ time calc_bc.sh
1000

real    0m56.576s
user    0m9.353s
sys     0m24.618s
$ time ./calc_awk.sh
100

real    0m11.672s
user    0m2.604s
sys     0m2.660s

說明: time 命令可以用來統(tǒng)計(jì)命令執(zhí)行時(shí)間,這部分時(shí)間包括總的運(yùn)行時(shí)間,用戶空間執(zhí)行時(shí)間,內(nèi)核空間執(zhí)行時(shí)間,它通過 ptrace 系統(tǒng)調(diào)用實(shí)現(xiàn)。

通過上述比較可以發(fā)現(xiàn) (()) 的運(yùn)算效率最高。而 let 作為 Shell 內(nèi)置命令,效率也很高,但是 expr,bc,awk 的計(jì)算效率就比較低。所以,在 Shell 本身能夠完成相關(guān)工作的情況下,建議優(yōu)先使用 Shell 本身提供的功能。但是 Shell 本身無法完成的功能,比如浮點(diǎn)運(yùn)算,所以就需要外部命令的幫助。另外,考慮到 Shell 腳本的可移植性,在性能不是很關(guān)鍵的情況下,不要使用某些 Shell 特有的語法。

let,expr,bc 都可以用來求模,運(yùn)算符都是 %,而 letbc 可以用來求冪,運(yùn)算符不一樣,前者是 **,后者是 ^ 。例如:

范例:求模

$ expr 5 % 2
1

$ let i=5%2
$ echo $i
1

$ echo 5 % 2 | bc
1

$ ((i=5%2))
$ echo $i
1

范例:求冪

$ let i=5**2
$ echo $i
25

$ ((i=5**2))
$ echo $i

25
$ echo "5^2" | bc
25

范例:進(jìn)制轉(zhuǎn)換

進(jìn)制轉(zhuǎn)換也是比較常用的操作,可以用 Bash 的內(nèi)置支持也可以用 bc 來完成,例如把 8 進(jìn)制的 11 轉(zhuǎn)換為 10 進(jìn)制,則可以:

$ echo "obase=10;ibase=8;11" | bc -l
9

$ echo $((8#11))
9

上面都是把某個(gè)進(jìn)制的數(shù)轉(zhuǎn)換為 10 進(jìn)制的,如果要進(jìn)行任意進(jìn)制之間的轉(zhuǎn)換還是 bc 比較靈活,因?yàn)樗梢灾苯佑?ibaseobase 分別指定進(jìn)制源和進(jìn)制轉(zhuǎn)換目標(biāo)。

范例:ascii 字符編碼

如果要把某些字符串以特定的進(jìn)制表示,可以用 od 命令,例如默認(rèn)的分隔符 IFS 包括空格、 TAB 以及換行,可以用 man ascii 佐證。

$ echo -n "$IFS" | od -c
0000000      t  n
0000003
$ echo -n "$IFS" | od -b
0000000 040 011 012
0000003

浮點(diǎn)運(yùn)算

letexpr 都無法進(jìn)行浮點(diǎn)運(yùn)算,但是 bcawk 可以。

范例:求 1 除以 13,保留 3 位有效數(shù)字

$ echo "scale=3; 1/13"  | bc
.076

$ echo "1 13" | awk '{printf("%0.3fn",$1/$2)}'
0.077

說明: bc 在進(jìn)行浮點(diǎn)運(yùn)算時(shí)需指定精度,否則默認(rèn)為 0,即進(jìn)行浮點(diǎn)運(yùn)算時(shí),默認(rèn)結(jié)果只保留整數(shù)。而 awk 在控制小數(shù)位數(shù)時(shí)非常靈活,僅僅通過 printf 的格式控制就可以實(shí)現(xiàn)。

補(bǔ)充:在用 bc 進(jìn)行運(yùn)算時(shí),如果不用 scale 指定精度,而在 bc 后加上 -l 選項(xiàng),也可以進(jìn)行浮點(diǎn)運(yùn)算,只不過這時(shí)的默認(rèn)精度是 20 位。例如:

$ echo 1/13100 | bc -l
.00007633587786259541

范例:余弦值轉(zhuǎn)角度

bc -l 計(jì)算,可以獲得高精度:

$ export cos=0.996293; echo "scale=100; a(sqrt(1-$cos^2)/$cos)*180/(a(1)*4)" | bc -l
4.934954755411383632719834036931840605159706398655243875372764917732
5495504159766011527078286004072131

當(dāng)然也可以用 awk 來計(jì)算:

$ echo 0.996293 | awk '{ printf("%s\n", atan2(sqrt(1-$1^2),$1)*180/3.1415926535);}'
4.93495

范例:有一組數(shù)據(jù),求人均月收入最高家庭

在這里隨機(jī)產(chǎn)生了一組測(cè)試數(shù)據(jù),文件名為 income.txt。

1 3 4490
2 5 3896
3 4 3112
4 4 4716
5 4 4578
6 6 5399
7 3 5089
8 6 3029
9 4 6195
10 5 5145

說明:上面的三列數(shù)據(jù)分別是家庭編號(hào)、家庭人數(shù)、家庭月總收入。

分析:為了求月均收入最高家庭,需要對(duì)后面兩列數(shù)進(jìn)行除法運(yùn)算,即求出每個(gè)家庭的月均收入,然后按照月均收入排序,找出收入最高家庭。

實(shí)現(xiàn):

#!/bin/bash
# gettopfamily.sh

[ $# -lt 1 ] && echo "please input the income file" && exit -1
[ ! -f $1 ] && echo "$1 is not a file" && exit -1

income=$1
awk '{
    printf("%d %0.2fn", $1, $3/$2);
}' $income | sort -k 2 -n -r

說明:

  • [ $# -lt 1 ]:要求至少輸入一個(gè)參數(shù),$# 是 Shell 中傳入?yún)?shù)的個(gè)數(shù)
  • [ ! -f $1 ]:要求輸入?yún)?shù)是一個(gè)文件,-f 的用法見 test 命令,man test
  • income=$1:把輸入?yún)?shù)賦給 income 變量,再作為 awk 的參數(shù),即需處理的文件
  • awk:用文件第三列除以第二列,求出月均收入,考慮到精確性,保留了兩位精度
  • sort -k 2 -n -r:這里對(duì)結(jié)果的 awk 結(jié)果的第二列 -k 2,即月均收入進(jìn)行排序,按照數(shù)字排序 -n,并按照遞減的順序排序 -r。

演示:

$ ./gettopfamily.sh income.txt
7 1696.33
9 1548.75
1 1496.67
4 1179.00
5 1144.50
10 1029.00
6 899.83
2 779.20
3 778.00
8 504.83

補(bǔ)充:之前的 income.txt 數(shù)據(jù)是隨機(jī)產(chǎn)生的。在做一些實(shí)驗(yàn)時(shí),往往需要隨機(jī)產(chǎn)生一些數(shù)據(jù),在下一小節(jié),我們將詳細(xì)介紹它。這里是產(chǎn)生 income.txt 數(shù)據(jù)的腳本:

#!/bin/bash
# genrandomdata.sh

for i in $(seq 1 10)
do
    echo $i $(($RANDOM/8192+3)) $((RANDOM/10+3000))
done

說明:上述腳本中還用到seq命令產(chǎn)生從1到10的一列數(shù),這個(gè)命令的詳細(xì)用法在該篇最后一節(jié)也會(huì)進(jìn)一步介紹。

隨機(jī)數(shù)

環(huán)境變量 RANDOM 產(chǎn)生從 0 到 32767 的隨機(jī)數(shù),而 awkrand() 函數(shù)可以產(chǎn)生 0 到 1 之間的隨機(jī)數(shù)。

范例:獲取一個(gè)隨機(jī)數(shù)

$ echo $RANDOM
81

$ echo "" | awk '{srand(); printf("%f", rand());}'
0.237788

說明: srand() 在無參數(shù)時(shí),采用當(dāng)前時(shí)間作為 rand() 隨機(jī)數(shù)產(chǎn)生器的一個(gè) seed 。

范例:隨機(jī)產(chǎn)生一個(gè)從 0 到 255 之間的數(shù)字

可以通過 RANDOM 變量的縮放和 awkrand() 的放大來實(shí)現(xiàn)。

$ expr $RANDOM / 128

$ echo "" | awk '{srand(); printf("%d\n", rand()*255);}'

思考:如果要隨機(jī)產(chǎn)生某個(gè) IP 段的 IP 地址,該如何做呢?看例子:友善地獲取一個(gè)可用的 IP 地址。

#!/bin/bash
# getip.sh -- get an usable ipaddress automatically
# author: falcon &lt;zhangjinw@gmail.com>
# update: Tue Oct 30 23:46:17 CST 2007

# set your own network, default gateway, and the time out of "ping" command
net="192.168.1"
default_gateway="192.168.1.1"
over_time=2

# check the current ipaddress
ping -c 1 $default_gateway -W $over_time
[ $? -eq 0 ] && echo "the current ipaddress is okey!" && exit -1;

while :; do
    # clear the current configuration
    ifconfig eth0 down
    # configure the ip address of the eth0
    ifconfig eth0 \
        $net.$(($RANDOM /130 +2)) \
        up
    # configure the default gateway
    route add default gw $default_gateway
    # check the new configuration
    ping -c 1 $default_gateway -W $over_time
    # if work, finish
    [ $? -eq 0 ] && break
done

說明:如果你的默認(rèn)網(wǎng)關(guān)地址不是 192.168.1.1,請(qǐng)自行配置 default_gateway(可以用 route -n 命令查看),因?yàn)橛?ifconfig 配置地址時(shí)不能配置為網(wǎng)關(guān)地址,否則你的IP地址將和網(wǎng)關(guān)一樣,導(dǎo)致整個(gè)網(wǎng)絡(luò)不能正常工作。

其他運(yùn)算

其實(shí)通過一個(gè)循環(huán)就可以產(chǎn)生一系列數(shù),但是有相關(guān)工具為什么不用呢!seq 就是這么一個(gè)小工具,它可以產(chǎn)生一系列數(shù),你可以指定數(shù)的遞增間隔,也可以指定相鄰兩個(gè)數(shù)之間的分割符。

范例:獲取一系列數(shù)

$ seq 5
1
2
3
4
5
$ seq 1 5
1
2
3
4
5
$ seq 1 2 5
1
3
5
$ seq -s: 1 2 5
1:3:5
$ seq 1 2 14
1
3
5
7
9
11
13
$ seq -w 1 2 14
01
03
05
07
09
11
13
$ seq -s: -w 1 2 14
01:03:05:07:09:11:13
$ seq -f "0x%g" 1 5
0x1
0x2
0x3
0x4
0x5

一個(gè)比較典型的使用 seq 的例子,構(gòu)造一些特定格式的鏈接,然后用 wget 下載這些內(nèi)容:

$ for i in `seq -f"http://thns.tsinghua.edu.cn/thnsebooks/ebook73/%02g.pdf" 1 21`;do wget -c $i; done

或者

$ for i in `seq -w 1 21`;do wget -c "http://thns.tsinghua.edu.cn/thnsebooks/ebook73/$i"; done

補(bǔ)充:在 Bash 版本 3 以上,在 for 循環(huán)的 in 后面,可以直接通過 {1..5} 更簡(jiǎn)潔地產(chǎn)生自 1 到 5 的數(shù)字(注意,1 和 5 之間只有兩個(gè)點(diǎn)),例如:

$ for i in {1..5}; do echo -n "$i "; done
1 2 3 4 5

范例:統(tǒng)計(jì)字符串中各單詞出現(xiàn)次數(shù)

我們先給單詞一個(gè)定義:由字母組成的單個(gè)或者多個(gè)字符系列。

首先,統(tǒng)計(jì)每個(gè)單詞出現(xiàn)的次數(shù):

$ wget -c http://tinylab.org
$ cat index.html | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | uniq -c

接著,統(tǒng)計(jì)出現(xiàn)頻率最高的前10個(gè)單詞:

$ wget -c http://tinylab.org
$ cat index.html | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | uniq -c | sort -n -k 1 -r | head -10
    524 a
    238 tag
    205 href
    201 class
    193 http
    189 org
    175 tinylab
    174 www
    146 div
    128 title

說明:

  • cat index.html: 輸出 index.html 文件里的內(nèi)容
  • sed -e "s/[^a-zA-Z]/\n/g": 把非字母字符替換成空格,只保留字母字符
  • grep -v ^$: 去掉空行
  • sort: 排序
  • uniq -c:統(tǒng)計(jì)相同行的個(gè)數(shù),即每個(gè)單詞的個(gè)數(shù)
  • sort -n -k 1 -r:按照第一列 -k 1 的數(shù)字 -n 逆序 -r 排序
  • head -10:取出前十行

范例:統(tǒng)計(jì)指定單詞出現(xiàn)次數(shù)

可以考慮采取兩種辦法:

  • 只統(tǒng)計(jì)那些需要統(tǒng)計(jì)的單詞
  • 用上面的算法把所有單詞的個(gè)數(shù)都統(tǒng)計(jì)出來,然后再返回那些需要統(tǒng)計(jì)的單詞給用戶

不過,這兩種辦法都可以通過下面的結(jié)構(gòu)來實(shí)現(xiàn)。先看辦法一:

#!/bin/bash
# statistic_words.sh

if [ $# -lt 1 ]; then
    echo "Usage: basename $0 FILE WORDS ...."
    exit -1
fi

FILE=$1
((WORDS_NUM=$#-1))

for n in $(seq $WORDS_NUM)
do
    shift
    cat $FILE | sed -e "s/[^a-zA-Z]/\n/g" \
        | grep -v ^$ | sort | grep ^$1$ | uniq -c
done

說明:

  • if 條件部分:要求至少兩個(gè)參數(shù),第一個(gè)單詞文件,之后參數(shù)為要統(tǒng)計(jì)的單詞
  • FILE=$1: 獲取文件名,即腳本之后的第一個(gè)字符串
  • ((WORDS_NUM=$#-1)):獲取單詞個(gè)數(shù),即總的參數(shù)個(gè)數(shù) $# 減去文件名參數(shù)(1個(gè))
  • for 循環(huán)部分:首先通過 seq 產(chǎn)生需要統(tǒng)計(jì)的單詞個(gè)數(shù)系列,shift 是 Shell 內(nèi)置變量(請(qǐng)通過 help shift 獲取幫助),它把用戶從命令行中傳入的參數(shù)依次往后移動(dòng)位置,并把當(dāng)前參數(shù)作為第一個(gè)參數(shù)即 $1,這樣通過 $1就可以遍歷用戶所有輸入的單詞(仔細(xì)一想,這里貌似有數(shù)組下標(biāo)的味道)。你可以考慮把 shift 之后的那句替換成 echo $1 測(cè)試 shift 的用法

演示:

$ chmod +x statistic_words.sh
$ ./statistic_words.sh index.html tinylab linux python
    175 tinylab
     43 linux
      3 python

再看辦法二,我們只需要修改 shift 之后的那句即可:

#!/bin/bash
# statistic_words.sh

if [ $# -lt 1 ]; then
    echo "ERROR: you should input 2 words at least";
    echo "Usage: basename $0 FILE WORDS ...."
    exit -1
fi

FILE=$1
((WORDS_NUM=$#-1))

for n in $(seq $WORDS_NUM)
do
    shift
    cat $FILE | sed -e "s/[^a-zA-Z]/\n/g" \
        | grep -v ^$ | sort | uniq -c | grep " $1$"
done

演示:

$ ./statistic_words.sh index.html tinylab linux python
    175 tinylab
     43 linux
      3 python

說明:很明顯,辦法一的效率要高很多,因?yàn)樗崆罢页隽诵枰y(tǒng)計(jì)的單詞,然后再統(tǒng)計(jì),而后者則不然。實(shí)際上,如果使用 grep-E 選項(xiàng),我們無須引入循環(huán),而用一條命令就可以搞定:

$ cat index.html | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | grep -E "^tinylab$|^linux$" | uniq -c
     43 linux
    175 tinylab

或者

$ cat index.html | sed -e "s/[^a-zA-Z]/\n/g" | grep -v ^$ | sort | egrep  "^tinylab$|^linux$" | uniq -c
     43 linux
    175 tinylab

說明:需要注意到 sed 命令可以直接處理文件,而無需通過 cat 命令輸出以后再通過管道傳遞,這樣可以減少一個(gè)不必要的管道操作,所以上述命令可以簡(jiǎn)化為:

$ sed -e "s/[^a-zA-Z]/\n/g" index.html | grep -v ^$ | sort | egrep  "^tinylab$|^linux$" | uniq -c
     43 linux
    175 tinylab

所以,可見這些命令 sed,grepuniq,sort 是多么有用,它們本身雖然只完成簡(jiǎn)單的功能,但是通過一定的組合,就可以實(shí)現(xiàn)各種五花八門的事情啦。對(duì)了,統(tǒng)計(jì)單詞還有個(gè)非常有用的命令 wc -w,需要用到的時(shí)候也可以用它。

補(bǔ)充:在 Advanced Bash-Scripting Guide 一書中還提到 jot 命令和 factor 命令,由于機(jī)器上沒有,所以沒有測(cè)試,factor 命令可以產(chǎn)生某個(gè)數(shù)的所有素?cái)?shù)。如:

$ factor 100
100: 2 2 5 5

小結(jié)

到這里,Shell 編程范例之?dāng)?shù)值計(jì)算就結(jié)束啦。該篇主要介紹了:

  • Shell 編程中的整數(shù)運(yùn)算、浮點(diǎn)運(yùn)算、隨機(jī)數(shù)的產(chǎn)生、數(shù)列的產(chǎn)生
  • Shell 的內(nèi)置命令、外部命令的區(qū)別,以及如何查看他們的類型和幫助
  • Shell 腳本的幾種執(zhí)行辦法
  • 幾個(gè)常用的 Shell 外部命令: sed,awk,grepuniqsort
  • 范例:數(shù)字遞增;求月均收入;自動(dòng)獲取 IP 地址;統(tǒng)計(jì)單詞個(gè)數(shù)
  • 其他:相關(guān)用法如命令列表,條件測(cè)試等在上述范例中都已涉及,請(qǐng)認(rèn)真閱讀之

如果您有時(shí)間,請(qǐng)溫習(xí)之。

資料

后記

大概花了 3 個(gè)多小時(shí)才寫完,目前是 23:33,該回宿舍睡覺啦,明天起來修改錯(cuò)別字和補(bǔ)充一些內(nèi)容,朋友們晚安!

10 月 31 號(hào),修改部分措辭,增加一篇統(tǒng)計(jì)家庭月均收入的范例,添加總結(jié)和參考資料,并用附錄所有代碼。

Shell 編程是一件非常有趣的事情,如果您想一想:上面計(jì)算家庭月均收入的例子,然后和用 M$ Excel 來做這個(gè)工作比較,你會(huì)發(fā)現(xiàn)前者是那么簡(jiǎn)單和省事,而且給您以運(yùn)用自如的感覺。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)