您好,登錄后才能下訂單哦!
bc
bc 是一種算數語言,其語法和c語言類似,可以交互執行。 通過命令行選項可以獲得一個標準的數學庫。如果請求,在處理任何文件之前定義數學庫。BC從處理所有文件的代碼開始。命令行中列出的文件按所列順序排列。在處理完所有文件后,BC從標準輸入中讀取。所有代碼都在讀取時執行。(如果文件包含停止處理器的命令,BC將永遠不會從標準輸入中讀取。
此命令的適用范圍:RedHat、RHEL、Ubuntu、CentOS、SUSE、openSUSE、Fedora。
1 、語法
bc [ -hlwsqv ] [long-options] [ file ... ]
2 、選項列表
選項 |
說明 |
-h | --help |
幫助信息 |
-v | --version |
顯示命令版本信息 |
-l | --mathlib |
定義標準數學庫 |
-i | --interactive |
強制交互 |
-w | --warn |
顯示POSIX的警告信息 |
-s | --standard |
使用POSIX標準來處理 |
-q | --quiet |
不顯示歡迎信息 |
3 、說明
1 )數據
bc 中最基本的元素是數字。數字是任意精度的數字。這種精度既包括整數部分,也包括分數部分。所有的數字在內部用十進制表示,所有的計算都用十進制來表示。(此版本截斷除法和乘運算的結果。)數字有兩個屬性:長度和小數位。長度是數字中有效位的總數,小數位是小數點之后的的有效位數。例如,0.000001的長度是6,小數位是6;1935.000的長度是7,小數位是3。
2 )變量
數字存儲在兩種類型的變量中,簡單變量和數組。變量名稱以字母開頭,后面跟著任意數量的字母、數字和下劃線。所有字母都必須小寫。(全字母-數字名是擴展名。在POSIX bc中,所有名稱都是一個小寫字母。)變量的類型在上下文中是明確的,因為所有數組變量名稱后面都會有方括號([])。
有四個特殊的變量:scale、ibase、obase和last。scale定義了一些操作在小數點之后是如何使用數字的,默認值是0。ibase和obase定義輸入和輸出數字的轉換基。默認值都是基數10。last(擴展)是一個變量。它是最后打印的數字的值。所有這些變量可能都有分配給它們的值,以及表達式中使用的值。
3 )注釋
bc 中的注釋以字符“/*”開頭,以字符“*/”結尾。注釋可以從任何地方開始,并顯示為輸入中的單個空格。(這會導致注釋分隔其他輸入項。例如,在變量名的中間找不到注釋。)注釋包括注釋開始和結束之間的任何新行(行尾)。
為了支持bc腳本的使用,添加了行注釋作為擴展。行注釋從“#”字符開始,繼續到行的結束。行結束字符不是注釋的一部分,而是正常處理的。
如果命令行上的任何文件無法打開,bc將報告該文件不可用并終止。
4 、關于表達式
這些數字由表達式和語句操作。由于語言設計為交互式,所以語句和表達式會盡快執行。沒有“主”程序,而是在遇到時執行代碼。
一個簡單的表達式只是一個常量。BC使用變量ibase指定的當前輸入基將常量轉換為內部十進制數。(函數中有一個例外。)ibase的有效值為2到16,將超出此范圍之后,分配給ibase的值可能是2或16。輸入數字可能包含字符0-9和A-F。(注:它們必須是大寫字母,小寫字母是變量名稱。)無論ibase的值是多少,單數數字總是有該數字的值。(即A=10。)對于多位數字,bc將所有大于或等于ibase的輸入數字更改為IBASE-1的值。這使得FFF始終輸入的最大3位數。
完全表達式類似于許多其他高級語言。由于只有一種數字,所以沒有混合類型的規則。相反,有關于表達式精度的規則。每個表達式都有一個精度。這是從原始數字的精度、所執行的操作以及在許多情況下變量scale的值導出的。變量scale的有效值為0到可由c語言整數表達的最大值。
在以下合法表達式的描述中,“expr”指的是一個完整的表達式,“var”指的是一個簡單的或數組變量。除非特別提到,結果的精度是所涉及的表達式的最大精度。
普通表達式 |
說明 |
-expr |
結果是對表達式的否定。 |
++var |
變量增加1,而新值是表達式的結果 |
--var |
變量減1,而新值是表達式的結果 |
var++ |
表達式的結果是變量的值,然后變量增加1 |
var-- |
表達式的結果是變量的值,然后變量減1 |
expr * expr |
表達式的結果是這兩個表達式的乘積 |
expr + expr |
表達式的結果是這兩個表達式的和 |
expr – expr |
表達式的結果是這兩個表達式的差 |
expr / expr |
表達式的結果是這兩個表達式的商。結果的精度是變量scale的值。 |
expr % expr |
表達式的結果是“余數” |
expr ^ expr |
表達式的結果是n次方,第二個表達式必須是整數。如果指數是負數,那么結果的精度是scale |
(expr) |
強制對表達式進行計算 |
var = expr |
變量就是表達式的值 |
var <op>= expr |
相當于“var=var<op>expr”,例如”var -= expr” 等價于“var=var-expr” |
關系表達式 |
關系表達式是一種特殊的表達式,計算結果總是0或1。如果關系為真,則計算為1;如果關系為假,則結果是0.。這些表達式可能出現在任何合法表達式中。(POSIX bc要求關系表達式僅用于if、while和語句,并且只能在其中進行一次關系測試。) |
||
expr1 < expr2 |
expr1 <= expr2 |
expr1 > expr2 |
expr1 >= expr2 |
expr1 == expr2 |
expr1 != expr2 |
expr1 && expr2 |
expr1 || expr2 |
!expr |
|
|
|
運算符的優先級如下,從上到下依次增加:
運算符 |
結合方式 |
|| |
左結合 |
&& |
左結合 |
! |
不結合 |
關系運算符 |
左結合 |
賦值運算符 |
右結合 |
+ 和- |
左結合 |
* 、/、% |
左結合 |
^ |
右結合 |
一元運算符 - |
不結合 |
++ 和-- |
不結合 |
選擇此優先級是為了使符合POSIX的bc程序能夠正確運行。這將導致關系運算符和邏輯運算符在與賦值表達式一起使用時有一些不尋常的行為。例如下面的表達式:
a = 3<5
大多數C程序員會假設這會將“3<5”(值1)的結果賦給變量“a”,這在bc中所做的是將值3賦給變量“a”,然后比較3到5。在使用關系運算符和邏輯運算符與賦值運算符時,最好使用括號。
在bc中還提供了一些特殊的表達式。這些表達式與用戶定義的函數和標準函數有關。它們都以“名稱(參數)”的形式出現。有幾個標準函數:
1 )length(expr),計算表達式結果的有效位數。
2 )read(),Read函數(一個擴展)將從標準輸入中讀取一個數字,而不管該函數發生在何處。注意,這可能會導致標準輸入中的數據和程序混合出現問題。這個函數的最佳使用是在一個已經編寫好的程序中,這個程序需要用戶輸入,但絕不允許從用戶輸入程序代碼。讀函數的值是從標準輸入中讀取的數字,使用轉換基的變量ibase的當前值。
· 3)scale ( expr ),這個函數的值是expr表達式中小數點之后的位數。
4 )sqrt ( expression ),函數的結果是表達式的開方值。
5 、關于語句
語句(在大多數代數語言中)提供表達式計算的順序。在bc中,語句被“盡快”執行。執行發生在遇到的換行符的時候,并且有一個或多個完整的語句。由于這種立即執行,換行符在bc中非常重要。事實上,分號和換行符都用作語句分隔符。如果換行符放置不當,將導致語法錯誤。因為換行符是語句分隔符,所以可以使用反斜杠字符隱藏換行符。(<nl>)在bc中顯示為空格而不是新行。語句列表是由分號和換行符分隔的一系列語句。
1 )表達式
這條語句做兩件事之一。如果表達式以“<變量><賦值>.”開頭,則被認為是賦值語句。如果表達式不是賦值語句,則計算表達式并將表達式打印到輸出。在打印數字之后,將打印換行符。例如,“a=1”是一個賦值語句和“(a=1)”是一個具有內嵌賦值的表達式。輸出基obase的有效值是2~ BC_BASE_MAX 。對于基數2至16,通常采用書寫數字的方法。對于大于16的基數,bc使用多字符數字方法將每個較高的基數打印成以10為基數的數據。由于數字具有任意精度,一些數字可能無法在一條輸出線上打印。這些長數字將被分割,以“\”作為一行上的最后一個字符,每行打印的最大字符數為70個。由于bc的交互性,打印一個數字會導致最后將打印值賦值給特殊變量“last”的副作用。這允許用戶恢復打印的最后一個值,而不必重新鍵入打印數字的表達式。將last變量賦值為“最后一個值”是合法的,并將最后一個打印的值用指定的值覆蓋。新賦值將保持不變,直到打印下一個數字或將另一個值分配給“last”為止。
2 )字符串
字符串被打印到輸出。字符串以雙引號開始,包含所有字符直到下一個雙引號字符。所有字符都是字面意思,包括任何換行符。字符串后不打印換行符。
3 )打印列表
print 語句(擴展)提供了另一種輸出方法。“list”是由逗號分隔的字符串和表達式的列表。每個字符串或表達式都按列表的順序打印。不打印終止換行符。表達式的將被計算出值,最后將其值打印并分配給變量“last”。打印語句中的字符串將打印到輸出中,并可能包含特殊字符。特殊字符以反斜杠字符“\”開始。bc識別的特殊字符是“a”(警報或鐘)、“b”(反斜杠)、“f”(表單提要)、“n”(換行符)、“r”(回車)、“q”(雙引號)、“t”(制表符)和“\”(反斜杠)。反斜杠后面的任何其他字符都將被忽略。
4 )語句列表
這是復合語句。它允許將多個語句組合在一起執行。
5 )if (表達式) statement 1 [else statement 2]
if 語句根據表達式的值決定執行statement 1或statement 2。如果表達式為非零,則執行statement 1。如果存在statement 2,且表達式的值為0的時候執行statement 2。
6 )while ( expression ) statement
while 語句將在表達式為非零時執行語句。它在每次執行語句之前計算表達式。循環的終止是由零表達式值或break語句的執行引起的。
7 )for ( [expression1] ; [expression2] ; [expression3] ) statement
for 語句控制語句的重復執行。表達式1是在循環之前計算的。表達式2是在每次語句執行之前計算的。如果表達式2為非零,則計算語句;如果為零,則終止循環。每次執行語句后,計算表達式3。在重新計算表達式2之前,如果未找到表達式1或表達式3,則不會在計算值的點上對其進行任何計算。
8 )break
break 語句用來強制退出,通常用在for語句或者while語句中。
9 )continue
continue 語句用來結束本次循環。
10 )halt
halt 語句會導致bc程序退出。
11 )return
函數返回0.
12 )return expr
返回表達式的值。
13 )偽語句,這些語句不會執行,他們在編譯的時候才會起作用。下面列出偽語句
a )limits,打印由于bc版本而產生的限制
b )quit,遇到quit指令的時候就會退出bc,無論它出現在什么地方。例如“if (0 == 1) quit”就會導致退出bc
c )warranty,打印較長的授權通知
6 、函數
1 )函數
bc 中的函數總是計算一個值并將其返回給調用者。函數定義是“動態的”,在輸入中遇到定義之前,函數是未定義的。然后使用該定義,直到遇到相同名稱的另一個定義函數。然后,新定義取代舊的定義。函數定義方式如下:
define name ( parameters ) { newline
auto_list statement_list }
函數的調用很簡單“name(parameters)”。
2 )參數
參數是數字或數組。在函數定義中,可以有0個或者多個參數,通過逗號分隔開。所有參數都是通過值參數調用的。數組是通過符號“name[]在參數定義中指定的。在函數調用中,實參是數字參數的完整表達式。相同的符號。數組的定義和傳值使用相同的符號。命名數組通過值傳遞給函數。由于函數定義是動態的,因此在調用函數時會檢查參數號和類型。參數數量或類型的不匹配都會導致運行時錯誤。對未定義函數的調用也會出現運行時錯誤。
3 )auto_list
“auto_list”是供“本地”使用的變量的可選列表。auto_list的語法(如果存在)是“autoname,…;”。(分號是可選的。)每個名稱都是自動變量的名稱。數組可以使用與參數相同的表示法來指定。這些變量的值在函數開始時被推入堆棧中。然后將變量初始化為零,并在函數的整個執行過程中使用。在函數退出時,這些變量被彈出,以便恢復這些變量的原始值(在函數調用時)。這些參數實際上是自動變量,它們被初始化為函數調用中提供的值。自動變量不同于傳統局部變量,因為如果函數A調用函數B,B可以使用相同的名稱訪問函數A的自動變量,除非函數B調用它們為自動變量。由于自動變量和參數被推到堆棧上,bc支持遞歸函數。
4 )函數體
函數體是一系列bc語句的列表。同樣,語句用分號或換行符分隔。返回語句導致函數的終止和值的返回。返回語句有兩個版本。第一個形式“return”將值0返回給調用表達式。第二種形式“return (表達式)”計算表達式的值并將該值返回給調用表達式。在每個函數的末尾有一個隱含的“return (0)”。這允許一個函數終止并返回0,而不需要顯式返回語句。
函數還會改變變量ibase的用法。函數體中的所有常量都將在函數調用時使用ibase的值進行轉換。在函數執行過程中,ibase的更改將被忽略,但標準函數讀取除外,后者將始終使用ibase的當前值來轉換數字。
當前版本的bc,在函數中添加了幾個擴展。首先,定義的格式稍微放松了一些。標準要求開始大括號與定義關鍵字在同一行,所有其他部分必須在下面的行上。這個版本的bc將允許之前的任何數目的換行符。在函數的開頭支撐之后,例如,下面的定義是合法的:
define d (n) { return (2*n); }
define d (n)
{ return (2*n); }
5 )void類型
函數可以定義為void。空函數不返回值,因此可能不會在任何需要值的地方使用。空函數在輸入行調用時不會產生任何輸出。關鍵字void放在關鍵字定義和函數名稱之間。例如,請考慮下面的例子
define py (y) { print "--->", y, "<---", "0; }
define void px (x) { print "--->", x, "<---", "0; }
py(1)
--->1<---
0 // 由于py不是void,因此有默認返回值,因此這里打印了它的返回值,
px(1)
--->1<--- //px 是void類型,最后不會打印返回值
此外,還為數組添加了按變量調用。為了申明一個數組變量,函數中的數組參數是這樣定義的“*name[]” 。
7 、數學庫
1 )如果使用“-l”選項調用bc,則預加載一個數學庫,并將默認精度設置為20。數學庫中有一下的函數:
s (x),計算x的正弦值,x是弧度值。
c (x),計算x的余弦值,x是弧度值。
a (x),計算x的反正切值,返回弧度。
l (x),計算x的自然對數。
e (x),e的x次方。
j (n,x),從n到x的階數。
2 )例子
下面的句子可以將“pi”的值賦值給shell變量pi
pi = $(echo "scale=10; 4*a(1)" | bc -l)
|
下面的句子就是數學庫中e的次方定義方式
scale = 20 /* Uses the fact that e^x = (e^(x/2))^2 When x is small enough, we use the series: e^x = 1 + x + x^2/2! + x^3/3! + ... */ define e(x) { auto a, d, e, f, i, m, v, z
/* Check the sign of x. */ if (x<0) { m = 1 x = -x }
/* Precondition x. */ z = scale; scale = 4 + z + .44*x; while (x > 1) { f += 1; x /= 2; }
/* Initialize the variables. */ v = 1+x a = x d = 1 for (i=2; 1; i++) { e = (a *= x) / (d *= i) if (e == 0) { if (f>0) while (f--) v = v*v; scale = z if (m) return (1/v); return (v/1); } v += e }
}
|
下面的語句實現一個計算支票簿余額的簡單程序
|
下面的語句采用遞歸的方式計算x的階乘
|
8 、readline和libedit選項
可以編譯GNU bc(通過一個配置選項)來使用GNU readline輸入編輯器庫或bsd libedit庫。這允許用戶在將行發送到bc之前進行編輯。它還允許保存以前鍵入的行的歷史記錄。當選擇此選項時,bc還有一個特殊變量。變量“history”是保留的歷史記錄行數。對于readline,值-1表示不限制歷史記錄的行數,0將禁用歷史記錄功能,默認值為100。
9 、差別
這個版本的bc是從POSIX P 1003.2/D11草案中實現的,包含了與草案和傳統實現相比的一些區別和擴展,它不是以傳統的方式使bc(1)實現的,這個版本是一個解析和運行程序字節代碼轉換的單一進程。這里有一個“無文檔”選項(-c),它導致程序將字節碼輸出到標準輸出,而不是運行它。它主要用于調試解析器和準備數學庫。差異的一個主要來源是擴展,下面列出一些差異和擴展:
1 )LANG環境變量,此版本在處理lang環境變量和從lc_開始的所有環境變量時不符合POSIX標準。
2 )名字,傳統和POSIX bc都有用于函數、變量和數組的單字母名稱。它們被擴展為以字母開頭的多字符名稱,可以包含字母、數字和下劃線字符。
3 )字符串,字符串不允許包含NUL字符。POSIX表示所有字符都必須包含在字符串中。
4 )last,POSIX bc中沒有last變量。
5 )比較,POSIX bc只允許在if語句、while語句和for語句的第二個表達式中進行比較。
6 )if語句,POSIX bc中if語句沒有else。
7 )for語句,POIX bc中要求for語句中的3個表達式都必須具備。
8 )&&,||,!,POSIX bc中沒有邏輯運算。
9 )read,POSIX bc沒有read功能。
10 )打印語句,POSIX bc沒有打印語句。
11 )continue語句,POSIX bc沒有continue語句。
12 )return,POSIX bc要求return的表達式加括號。
13 )數組參數,POSIX bc不(目前)完全支持數組參數。POSIX語法允許函數定義中的數組,但沒有提供將數組指定為實際參數的方法。(這很可能是語法上的疏忽。)傳統的bc實現只通過值數組參數進行調用。
14 )函數,POSIX bc要求函數開頭的大括號和define關鍵字在同一行,語句在下一行。
15 )=+, =-, =*, =/, =%, =^。POSIX bc不要求定義這些“舊樣式”賦值操作符。此版本可能允許這些“舊樣式”賦值。使用限制語句查看安裝的版本是否支持它們。如果它確實支持“舊樣式”賦值運算符,則“a=-1”語句將使a減少1,而不是將a設置為值-1。
16 )數字中的空格,bc的其他實現允許數字空格。例如,“x=1 3”將值13賦值給變量x。相同的語句將導致bc版本中的語法錯誤。
17 )錯誤和執行,在程序中發現語法和其他錯誤時,此實現與其他實現的代碼不同。如果在函數定義中發現語法錯誤,則錯誤恢復機制將嘗試查找語句的開頭并繼續解析函數。一旦在函數中發現語法錯誤,該函數將不可調用并變為未定義。交互執行代碼中的語法錯誤將使當前執行塊失效。執行塊由在完整語句序列之后出現的行尾終止。例如
a = 1
b = 2
這個語句有兩個執行塊,而下面的語句
{a = 1
b = 2}
只有一個執行塊。任何運行時錯誤都會終止當前的執行塊,而警告則不會。
18 )中斷,在交互會話期間,SIGINT信號(通常由終端上的“ctrl+c“生成)將導致當前執行塊的執行中斷。它將顯示一個“運行時”錯誤,指示哪個功能被中斷。在所有運行時結構被清除后,將打印一條消息通知用戶bc準備好接收更多的輸入。所有先前定義的函數都保留定義,所有非自動變量的值是中斷點的值。在清理過程中,所有自動變量和函數參數都會被移除。對于一個非交互式會話,SIGINT信號將終止bc的整個運行。
10 、限制
下面列出當前bc程序的一些限制,有一些限制可能已經被用戶修改過。
1 )BC_BASE_MAX,最大輸出基設置為999。最大輸入基為16。
2 )BC_DIM_MAX,這是當前分布的65535以內的任意限制,每個機器可能都不一樣。
3 )BC_SCALE_MAX,小數點前后的位數都由INT_MAX限制。
4 )BC_STRING_MAX,字符串中的字符字數由INT_MAX限制。
5 )exponent,指數運算中的指數值由LONG_MAX限制。
6 )variable names,當前對每個簡單變量、數組和函數名字的限制32767。
11 、環境變量
下面的環境變量由bc程序來控制
1 )POSIXLY_CORRECT,和“-s”選項一樣。
2 )BC_ENV_ARGS,這是另一種獲取bc參數的機制。格式與命令行參數相同。這些參數是先處理的,因此環境參數中列出的任何文件在任何命令行參數文件之前都會被處理。這允許用戶設置“標準”選項和文件,以便在每次調用環境變量中的文件通常包含用戶希望在每次運行bc時定義的函數定義。
3 )BC_LINE_LENGTH,這應該是一個整數,指定數字輸出行中的字符數。這包括用于長數字的反斜杠和換行符。,如果值是0,將禁用多行功能。此變量的任何其他值如果小于3,則將行長設置為70。
12 、實例
1 )簡單計算
|
2 )執行for循環語句
|
3 )從文件讀取內容并且執行bc
[root@localhost /]# cat test.c // 查看文件的內容,里面全是 bc 語句 /*define 3 functions add,sub,mul*/ define add(x,y){ return x+y; } define sub(x,y){ return x-y; } define mul(x,y){ return x*y; } /*for statement*/ for(i=0;i<3;i++){ print "bc test ",i,"\n"; } /*print statement*/ print "10+5=",add(10,5),"\n" print "10-5=",sub(10,5),"\n" print "10&5=",mul(10,5),"\n" /*quit bc program*/ quit [root@localhost /]# bc test.c //bc 程序從文件獲取到代碼,然后執行 bc 1.06.95 Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc. This is free software with ABSOLUTELY NO WARRANTY. For details type `warranty'. bc test 0 bc test 1 bc test 2 10+5=15 10-5=5 10&5=50 |
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。