📄 mathc.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><HTML><HEAD><TITLE>数学计算命令</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINKREL="HOME"TITLE="高级Bash脚本编程指南"HREF="index.html"><LINKREL="UP"TITLE="外部过滤器, 程序和命令"HREF="external.html"><LINKREL="PREVIOUS"TITLE="终端控制命令"HREF="terminalccmds.html"><LINKREL="NEXT"TITLE="混杂命令"HREF="extmisc.html"></HEAD><BODYCLASS="SECT1"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">高级Bash脚本编程指南: 一本深入学习shell脚本艺术的书籍</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="terminalccmds.html"ACCESSKEY="P">前一页</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">12. 外部过滤器, 程序和命令</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="extmisc.html"ACCESSKEY="N">下一页</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="MATHC">12.8. 数学计算命令</A></H1><P></P><DIVCLASS="VARIABLELIST"><P><B><ANAME="MATHCOMMANDLISTING1"></A><SPANCLASS="QUOTE">"操作数字"</SPAN></B></P><DL><DT><BCLASS="COMMAND">factor</B></DT><DD><P>将一个正数分解为多个素数. </P><P> <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"><SAMPCLASS="PROMPT">bash$ </SAMP><KBDCLASS="USERINPUT">factor 27417</KBD><SAMPCLASS="COMPUTEROUTPUT">27417: 3 13 19 37</SAMP> </PRE></FONT></TD></TR></TABLE> </P></DD><DT><ANAME="BCREF"></A><BCLASS="COMMAND">bc</B></DT><DD><P>Bash不能处理浮点运算, 并且缺乏特定的一些操作, 这些操作都是一些重要的计算功能. 幸运的是, <BCLASS="COMMAND">bc</B>可以解决这个问题. </P><P><BCLASS="COMMAND">bc</B>不仅仅是个多功能灵活的精确计算工具, 且它还提供许多编程语言才具备的一些方便功能. </P><P><BCLASS="COMMAND">bc</B>比较类似于C语言的语法. </P><P>因为它是一个完整的UNIX工具, 所以它可以用在<AHREF="special-chars.html#PIPEREF">pipe</A>中, <BCLASS="COMMAND">bc</B>在脚本中也是很常用的. </P><P>这里有一个简单的使用<BCLASS="COMMAND">bc</B>命令的模版, 可以用来计算脚本中的变量. 这个模版经常用于<AHREF="commandsub.html#COMMANDSUBREF">命令替换</A>中. </P><P> <TABLEBORDER="1"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="SCREEN"> <KBDCLASS="USERINPUT">variable=$(echo "OPTIONS; OPERATIONS" | bc)</KBD> </PRE></FONT></TD></TR></TABLE> </P><DIVCLASS="EXAMPLE"><HR><ANAME="MONTHLYPMT"></A><P><B>例子 12-42. 按月偿还贷款</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # monthlypmt.sh: 计算按月偿还贷款的数量. 3 4 5 # 这份代码是一份修改版本, 原始版本在"mcalc"(贷款计算)包中, 6 #+ 这个包的作者是Jeff Schmidt和Mendel Cooper(本书作者). 7 # http://www.ibiblio.org/pub/Linux/apps/financial/mcalc-1.6.tar.gz [15k] 8 9 echo 10 echo "Given the principal, interest rate, and term of a mortgage," 11 echo "calculate the monthly payment." 12 13 bottom=1.0 14 15 echo 16 echo -n "Enter principal (no commas) " 17 read principal 18 echo -n "Enter interest rate (percent) " # 如果是12%, 那就键入"12", 而不是".12". 19 read interest_r 20 echo -n "Enter term (months) " 21 read term 22 23 24 interest_r=$(echo "scale=9; $interest_r/100.0" | bc) # 转换成小数. 25 # "scale"指定了有效数字的个数. 26 27 28 interest_rate=$(echo "scale=9; $interest_r/12 + 1.0" | bc) 29 30 31 top=$(echo "scale=9; $principal*$interest_rate^$term" | bc) 32 33 echo; echo "Please be patient. This may take a while." 34 35 let "months = $term - 1" 36 # ==================================================================== 37 for ((x=$months; x > 0; x--)) 38 do 39 bot=$(echo "scale=9; $interest_rate^$x" | bc) 40 bottom=$(echo "scale=9; $bottom+$bot" | bc) 41 # bottom = $(($bottom + $bot")) 42 done 43 # ==================================================================== 44 45 # -------------------------------------------------------------------- 46 # Rick Boivie给出了一个对上边循环的修改方案, 47 #+ 这个修改更加有效率, 将会节省大概2/3的时间. 48 49 # for ((x=1; x <= $months; x++)) 50 # do 51 # bottom=$(echo "scale=9; $bottom * $interest_rate + 1" | bc) 52 # done 53 54 55 # 然后他又想出了一个更加有效率的版本, 56 #+ 将会节省95%的时间! 57 58 # bottom=`{ 59 # echo "scale=9; bottom=$bottom; interest_rate=$interest_rate" 60 # for ((x=1; x <= $months; x++)) 61 # do 62 # echo 'bottom = bottom * interest_rate + 1' 63 # done 64 # echo 'bottom' 65 # } | bc` # 在命令替换中嵌入一个'for循环'. 66 # -------------------------------------------------------------------------- 67 # 另一方面, Frank Wang建议: 68 # bottom=$(echo "scale=9; ($interest_rate^$term-1)/($interest_rate-1)" | bc) 69 70 # 因为 . . . 71 # 在循环后边的算法 72 #+ 事实上是一个等比数列的求和公式. 73 # 求和公式是 e0(1-q^n)/(1-q), 74 #+ e0是第一个元素, q=e(n+1)/e(n), 75 #+ n是元素数量. 76 # -------------------------------------------------------------------------- 77 78 79 # let "payment = $top/$bottom" 80 payment=$(echo "scale=2; $top/$bottom" | bc) 81 # 使用2位有效数字来表示美元和美分. 82 83 echo 84 echo "monthly payment = \$$payment" # 在总和的前边显示美元符号. 85 echo 86 87 88 exit 0 89 90 91 # 练习: 92 # 1) 处理输入允许本金总数中的逗号. 93 # 2) 处理输入允许按照百分号和小数点的形式输入利率. 94 # 3) 如果你真正想好好编写这个脚本, 95 # 那么就扩展这个脚本让它能够打印出完整的分期付款表. </PRE></FONT></TD></TR></TABLE><HR></DIV><DIVCLASS="EXAMPLE"><HR><ANAME="BASE"></A><P><B>例子 12-43. 数制转换</B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 ########################################################################## 3 # 脚本 : base.sh - 用不同的数制来打印数字 (Bourne Shell) 4 # 作者 : Heiner Steven (heiner.steven@odn.de) 5 # 日期 : 07-03-95 6 # 类型 : 桌面 7 # $Id: base.sh,v 1.2 2000/02/06 19:55:35 heiner Exp $ 8 # ==> 上边这行是RCS ID信息. 9 ########################################################################## 10 # 描述 11 # 12 # 修改纪录 13 # 21-03-95 stv fixed error occuring with 0xb as input (0.2) 14 ########################################################################## 15 16 # ==> 在本书中使用这个脚本通过了原作者的授权. 17 # ==> 注释是本书作者添加的. 18 19 NOARGS=65 20 PN=`basename "$0"` # 程序名 21 VER=`echo '$Revision: 1.2 $' | cut -d' ' -f2` # ==> VER=1.2 22 23 Usage () { 24 echo "$PN - print number to different bases, $VER (stv '95) 25 usage: $PN [number ...] 26 27 If no number is given, the numbers are read from standard input. 28 A number may be 29 binary (base 2) starting with 0b (i.e. 0b1100) 30 octal (base 8) starting with 0 (i.e. 014) 31 hexadecimal (base 16) starting with 0x (i.e. 0xc) 32 decimal otherwise (i.e. 12)" >&2 33 exit $NOARGS 34 } # ==> 打印出用法信息的函数. 35 36 Msg () { 37 for i # ==> 省略[list]. 38 do echo "$PN: $i" >&2 39 done 40 } 41 42 Fatal () { Msg "$@"; exit 66; } 43 44 PrintBases () { 45 # 决定数字的数制 46 for i # ==> 省略[list]... 47 do # ==> 所以是对命令行参数进行操作. 48 case "$i" in 49 0b*) ibase=2;; # 2进制 50 0x*|[a-f]*|[A-F]*) ibase=16;; # 16进制 51 0*) ibase=8;; # 8进制 52 [1-9]*) ibase=10;; # 10进制 53 *) 54 Msg "illegal number $i - ignored" 55 continue;; 56 esac 57 58 # 去掉前缀, 将16进制数字转换为大写(bc命令需要这么做) 59 number=`echo "$i" | sed -e 's:^0[bBxX]::' | tr '[a-f]' '[A-F]'` 60 # ==> 使用":" 作为sed分隔符, 而不使用"/". 61 62 # 将数字转换为10进制 63 dec=`echo "ibase=$ibase; $number" | bc` # ==> 'bc'是个计算工具. 64 case "$dec" in 65 [0-9]*) ;; # 数字没问题 66 *) continue;; # 错误: 忽略 67 esac 68 69 # 在一行上打印所有转换后的数字. 70 # ==> 'here document'提供命令列表给'bc'. 71 echo `bc <<! 72 obase=16; "hex="; $dec 73 obase=10; "dec="; $dec 74 obase=8; "oct="; $dec 75 obase=2; "bin="; $dec 76 ! 77 ` | sed -e 's: : :g' 78 79 done 80 } 81 82 while [ $# -gt 0 ] 83 # ==> 这里必须使用一个"while循环", 84 # ==>+ 因为所有的case都可能退出循环或者 85 # ==>+ 结束脚本. 86 # ==> (感谢, Paulo Marcel Coelho Aragao.) 87 do 88 case "$1" in 89 --) shift; break;; 90 -h) Usage;; # ==> 帮助信息. 91 -*) Usage;; 92 *) break;; # 第一个数字 93 esac # ==> 对于非法输入进行更严格检查是非常有用的. 94 shift 95 done 96 97 if [ $# -gt 0 ] 98 then 99 PrintBases "$@"100 else # 从stdin中读取101 while read line102 do103 PrintBases $line104 done105 fi106 107 108 exit 0</PRE></FONT></TD></TR></TABLE><HR></DIV><P>调用<BCLASS="COMMAND">bc</B>的另一种方法就是<AHREF="here-docs.html#HEREDOCREF">here document</A>, 并把它嵌入到<AHREF="commandsub.html#COMMANDSUBREF">命令替换</A>块中. 当一个脚本需要将一个选项列表和多个命令传递到<BCLASS="COMMAND">bc</B>中时, 这种方法就显得非常合适了. </P><P> <TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 variable=`bc << LIMIT_STRING 2 options 3 statements 4 operations 5 LIMIT_STRING 6 ` 7 8 ...or... 9 10 11 variable=$(bc << LIMIT_STRING 12 options 13 statements 14 operations 15 LIMIT_STRING 16 )</PRE></FONT></TD></TR></TABLE> </P><DIVCLASS="EXAMPLE"><HR><ANAME="ALTBC"></A><P><B>例子 12-44. 使用<SPANCLASS="QUOTE">"here document"</SPAN>来调用<BCLASS="COMMAND">bc</B></B></P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="90%"><TR><TD><FONTCOLOR="#000000"><PRECLASS="PROGRAMLISTING"> 1 #!/bin/bash 2 # 使用命令替换来调用'bc' 3 # 并与'here document'相结合. 4 5 6 var1=`bc << EOF 7 18.33 * 19.78 8 EOF 9 ` 10 echo $var1 # 362.56 11 12 13 # 使用$( ... )这种标记法也可以. 14 v1=23.53 15 v2=17.881 16 v3=83.501
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -