bc (执行任意精度数学计算的语言)

rose1 发表于 2020-08-13 11:48
浏览次数:
在手机上阅读

在类似Unix的操作系统上,bc是用于执行任意精度数学计算的语言,并且是该语言的交互式解释器。

查看英文版

目录

1 bc 运行系统环境

2 bc 说明

3 bc 语法

4 bc 例子

bc 运行系统环境

Linux

bc 说明

bc是一种支持任意精度数字的语言,这意味着无论数字有多大(或非常小),它都能提供准确的结果。

它具有交互模式,可以接受来自终端的输入并根据要求提供计算。作为一种语言,它的语法类似于C编程语言。使用命令行选项可以使用标准数学库。如果需要,则在处理任何文件之前先定义数学库。

bc首先以列出的顺序处理命令行中列出的所有文件中的代码。处理完所有文件后,bc从标准输入读取。所有代码都在读取时执行。

较新的bc版本包含了对传统bc实现和POSIX草案标准的扩展。命令行选项可能导致这些扩展名打印警告或被拒绝。本文档介绍了bc语言的较新版本。如果特定功能是标准的扩展,则在下面相应说明。

bc is a language that supports arbitrary-precision numbers, meaning that it delivers accurate results regardless of how large (or very small) the numbers are.

It has an interactive mode, accepting input from the terminal and providing calculations on request. As a language, its syntax is similar to the C programming language. A standard math library is available using a command line option. If requested, the math library is defined before processing any files.

bc starts by processing code from all the files listed on the command line in the order listed. After all files have been processed, bc reads from the standard input. All code is executed as it is read.

Newer versions of bc contain several extensions beyond traditional bc implementations and the POSIX draft standard. Command-line options can cause these extensions to print a warning or to be rejected. This document describes the newer version of the bc language; where a particular function is an extension of the standard, it is noted accordingly below.

查看英文版

查看中文版

bc 语法

bc [ -hlwsqv ] [long-options] [ file ... ]

选件

-h--help

打印帮助信息并退出。

-i--interactive

强制交互模式。

-l--mathlib

定义标准数学库。

-w--warn

对POSIX bc的扩展名发出警告。

-s--standard

精确处理POSIX bc语言。

-q--quiet

不要打印普通的GNU bc欢迎消息。

-v--version

打印版本号和版权信息,然后退出。

号码

bc中最基本的元素是数字。数字是任意精度的数字。此精度在整数部分和小数部分中都存在。所有数字内部均以十进制表示,所有计算均以十进制表示。某些版本的bc 截断是除法和乘法运算的结果。

数字有两个属性,长度和小数位数。长度是数字中有效十进制数字的总数,小数位数是小数点后的十进制数字的总数。例如:

.000001 的长度为6,小数位数为6。

1935.000 的长度为7,小数位数为3。

变数

数字存储在两种类型的变量中:简单变量和数组。简单变量和数组变量都被命名。名称以字母开头,后跟任意数量的字母,数字和下划线。所有字母必须为小写。全字母数字名称是扩展名。在POSIX bc中,所有名称均为单个小写字母。变量的类型在上下文中是清楚的,因为所有数组变量名都将后跟方括号([])。 Full alphanumeric names are an extension. In POSIX bc all names are a single lower case letter. The type of variable is clear by the context because all array variable names will be followed by brackets ([]).

有四个特殊变量:scale,ibase,obase和last。

标度定义某些操作如何使用小数点后的数字。scale的默认值为0。

ibaseobase定义输入和输出数字的转换基础。输入和输出的默认值为10。

last(扩展名)是一个具有最后打印数字的值的变量。

所有变量都可以分配有值,并且可以在表达式中使用。

注释

评论在公元前开始以字符“ / * ”和结束与字符“ * / ”。注释可以在任何地方开始,并在输入中显示为单个空格。这将导致注释分隔其他输入项。例如,注释不能放在变量名的中间。注释包括注释开头和结尾之间的任何换行符(行尾)。

为了支持对bc使用脚本,已添加一行注释作为扩展名。单行注释以“ # ”字符开头,并继续到下一行。行尾字符不是注释的一部分,可以正常处理。

表达方式

数字由表达式和语句操纵。由于该语言被设计为交互式的,因此语句和表达式将尽快执行。没有“主”程序;而是在遇到代码时执行代码。遇到功能时,将定义后面将详细讨论的功能。

一个简单的表达式只是一个常数。bc使用变量ibase指定的当前输入基数将常量转换为内部十进制数。函数中有一个例外。的合法值IBASE216。将超出此范围的值分配给ibase将得到2或16的值。输入数字可能包含字符0-9AF。注意:它们必须是大写字母。小写字母保留用于变量名。不管ibase的值如何,一位数字始终具有该数字的值。对于多位数,bc将所有大于或等于ibase的输入数字更改为ibase-1的值。这使得数字FFF始终是输入基数的最大3位数字。

完整表达式类似于其他高级语言。由于只有一种数字,因此没有混合变量类型的规则。取而代之的是在表达式范围内有规则。每个表达式都有一个比例,该比例是从原始数字的比例,执行的操作以及在许多情况下可变scale的值得出的。可变标度的合法值是0到C整数可表示的最大值。

在以下对合法表达式的描述中,“ expr ”是指完整表达式,而“ var ”是指简单变量或数组变量。一个简单的变量只是一个名称,而一个数组变量被指定为名称 [ expr ]。

除非特别说明,结果的标度是所涉及表达式的最大标度。

- expr - 结果是表达的否定。

++ var - 变量加1,新值是表达式的结果。

-- var - 变量被减一,新值是表达式的结果。

var ++ - 表达式的结果是变量的值,然后变量加1。

var -- - 表达的结果是该变量的值,然后该变量被减一。

expr + expr - 表达式的结果是两个表达式的总和。

expr - expr - 表达式的结果是两个表达式的差。

expr * expr - 表达式的结果是两个表达式的乘积。

expr / expr - 表达式的结果是两个表达式的商。结果的标度是可变标度的值。

expr % expr - 表达式的结果为“余数”,它的计算方式如下。为了计算一%b,第一一/ b被计算为比例位数。该结果被用来计算一个- (一/ b )* b的最大的规模规模+ 比例(b )和刻度(一)。如果将scale设置为零,并且两个表达式均为整数,则此表达式为整数余数函数。

expr ^ expr - 表达式的结果是第一个的值提高为第二个的幂。第二个表达式必须是整数。如果第二个表达式不是整数,则会生成警告,并且该表达式将被截断以获得整数值。如果指数为负,则结果的小数位数为小数位数。如果指数为正,则结果的标度是第一个表达式的标度的最小值乘以指数的值以及最大的标度和第一个表达式的标度。(例如scale(a ^ b )= min(scale (a )* b ,max( scale , scale (a )))。)应该注意,expr ^ 0将始终返回值1。

( expr ) - 这会更改标准优先级以强制对表达式进行求值。

var = expr - 为变量分配表达式的值。

var = expr - 此表达式等效于“ var = varexpr ”,不同之处在于“ var ”部分仅被评估一次。如果“ var ”是一个数组,这可以有所作为。

关系表达式是一种特殊的表达始终评估为0或1:0,如果关系是假的,1,如果关系是真实的。这些可能以任何法律表达形式出现。POSIX bc要求仅在if,while和for语句中使用关系表达式,并且只能在其中进行一个关系测试。关系运算符是:

expr1 < expr2

如果expr1严格小于expr2,则结果为1 。

expr1 <= expr2

其结果是1,如果expr1的是小于或等于表达式2。

expr1 > expr2

如果expr1严格大于expr2,则结果为1 。

expr1 >= expr2

其结果是1,如果表达式1大于或等于表达式2。

expr1 == expr2

如果expr1等于expr2,则结果为1 。

expr1 != expr2

如果expr1不等于expr2,则结果为1 。

布尔运算也是合法的。(POSIX bc没有布尔操作)。与关系表达式中一样,所有布尔运算的结果均为0和1(对于false和true)。布尔运算符为:

!expr

如果expr为0,则结果为1 。

expr && expr

如果两个表达式都不为零,则结果为1。

expr || expr

如果两个表达式都不为零,则结果为1。

表达式优先级如下:(从最低到最高)

  • || 操作员,左联想
  • && 运算符,左联想
  • ! 运算符,非关联
  • 关系运算符,左关联
  • 赋值运算符,右关联
  • + and - 运算符,左关联
  • */ 和%运算符,左关联
  • ^ 运算符,右关联
  • 元-运算符,非关联
  • ++ 和-运算符,非关联

选择该优先级是为了使符合POSIX的bc程序能够正确运行。与赋值表达式一起使用时,这将导致关系和逻辑运算符的使用具有某些异常行为。考虑以下表达式:

a = 3 < 5

大多数C程序员会假设这会将结果“ 3 <5 ”(值1)分配给变量“ a ”。这在bc中的作用是将值3分配给变量“ a ”,然后将35进行比较。将关系运算符和逻辑运算符与赋值运算符一起使用时,最好使用括号。

bc中提供了一些其他特殊表达式。这些与用户定义的功能和标准功能有关。它们都显示为“ 名称(参数) ”。有关用户定义的功能,请参见功能部分。标准功能是:

长度( 表达式 )

长度函数的值是表达式中的有效位数。

阅读()

读取功能(扩展)将从标准输入读取的数,而不管其中函数发生的。请注意,这可能会导致标准输入中数据和程序混合的问题。此功能的最佳用途是在先前编写的程序中,需要用户输入,但绝不允许用户输入程序代码。读取功能的值是使用转换基础的变量ibase的当前值从标准输入读取的数字。

规模( 表示 )

标度函数的值是表达式中小数点后的位数。

sqrt( 表达式 )

sqrt函数的值是表达式的平方根。如果表达式为负,则会生成运行时错误。

陈述

语句(与大多数代数语言一样)提供了表达评估的顺序。在bc中,语句“尽快”执行。当遇到换行符并且存在一个或多个完整语句时,将执行执行。由于立即执行,换行符在bc中很重要。实际上,分号和换行符都用作语句分隔符。换行符放置不当会导致语法错误。因为换行符是语句分隔符,所以可以使用反斜杠字符来隐藏换行符。序列“ \”(其中是换行符)在bc中显示为空白而不是换行符。语句列表是一系列由分号和换行符分隔的语句。以下是bc语句及其作用的列表:方括号([])中的内容是语句的可选部分。

表达

该语句执行以下两项操作之一。如果表达式以“... ” 开头,则将其视为分配语句。如果该表达式不是赋值语句,则对该表达式求值并打印到输出。号码打印后,将换行。例如,“ a = 1 ”是赋值语句,“ (a = 1) ”是具有嵌入式赋值的表达式。所有打印的数字均以变量obase指定的基数打印。obase的合法值为2到BC_BASE_MAX。(请参阅“限制”一节。)对于2到16的基数,使用通常的数字写方法。使用多字符数字方法来打印数字,其中每个较高的基数都将作为基数10打印。多字符数字用空格分隔。每个数字包含表示“ obase-1 ”的十进制值所需的字符数。由于数字具有任意精度,因此某些数字可能无法在单个输出行上打印。这些长数字将使用“ \ ”作为一行的最后一个字符而被分成几行。每行打印的最大字符数为70。由于bc的交互性质,打印数字会导致最后将打印值分配给特殊变量的副作用。此功能使用户可以恢复打印的最后一个值,而不必重新键入打印数字的表达式。分配给最后一个是合法的,并且将使用分配的值覆盖最后打印的值。新分配的值将一直保留到下一个数字被打印或最后一个值被分配为止。某些安装可能允许使用单个句点(。)作为数字的缩写形式,而不是数字的一部分。

该字符串将打印到输出中。字符串以双引号字符开头,并包含所有字符,直到下一个双引号字符为止。所有字符均按字面意义使用,包括任何换行符。字符串后不打印换行符。

打印 清单

打印语句(扩展)提供输出的另一方法。“列表”是由逗号分隔的字符串和表达式的列表。每个字符串或表达式都按照列表的顺序打印。没有终止换行符被打印。计算表达式并打印其值,最后将其分配给变量。打印语句中的字符串将打印到输出中,并且可以包含特殊字符。特殊字符以反斜杠字符(\)开头。bc识别的特殊字符是“ a ”(警报或铃声),“ b ”(退格键),“ f ”(换页),“ n ”(换行符),“ r ”“(双引号),“ t ”(制表符)和“ \ ”(反斜杠)。反斜杠后面的任何其他字符将被忽略。

{statement_list}

此选项是复合语句。它允许将多个语句组合在一起执行。

if (expression)statement1 [elsestatement2]

如果语句计算表达式并执行语句1或语句2取决于表达式的值。如果表达式非零,则执行statement1。如果存在statement2并且表达式的值为0,则执行statement2。在其他子句是一个扩展。

while( 表达式 ) 语句

同时表达为非零语句将执行该语句。它在每次执行该语句之前对表达式求值。循环的终止是由零表达式值或执行break语句引起的。

for ( [expression1] ; [expression2] ; [expression3] )statement

在对语句控制重复语句的执行。在循环之前对Expression1求值。在每次执行该语句之前对Expression2进行求值。如果非零,则对语句进行评估。如果为零,则终止循环。在每次执行该语句之后,在重新计算expression2之前先对expression3进行评估。如果缺少expression1expression3,则在将要评估它们时将不评估任何内容。如果缺少expression2,则与将值1替换为expression2相同。。可选表达式是扩展。POSIX bc需要所有三个表达式。以下是for语句的等效代码:

expression1; while (expression2) { statement; expression3; }

打破

该语句导致最近的while语句或for语句的强制退出。

继续

继续语句(扩展)导致最近的封闭for语句开始下一次迭代。

停止

停止声明(扩展),是一个执行的语句引起BC被执行时,它向处理器仅退出。例如,“ if(0 == 1)halt ”将不会导致bc终止,因为未执行暂停。

返回

从函数返回值0。(请参阅有关功能的部分。)

返回( 表达式 )

从函数返回表达式的值。(请参见函数部分。)作为扩展,不需要括号。

伪陈述

这些陈述不是传统意义上的陈述。它们不是已执行的语句。它们的功能在“编译”时执行。

极限

打印由本地版本bc强制执行的本地限制。(这是一个扩展。)

退出

退出读声明时,卑诗处理器被终止,无论在哪里退出声明中找到。例如,“ if(0 == 1)quit ”将导致bc终止。

保证

打印保修通知。(这是一个扩展。)

功能

函数提供了一种定义可以稍后执行的计算的方法。bc中的函数总是计算值并将其返回给调用方。函数定义是“动态的”,即直到在输入中遇到定义之前才定义函数。然后使用该定义,直到遇到另一个具有相同名称的定义函数。然后,新定义将替换旧定义。函数定义如下:

define name ( parameters ) { newline auto_list statement_list }

函数调用只是形式为“名称(参数)”的表达式。

参数是数字或数组(扩展名)。在函数定义中,零个或多个参数通过列出用逗号分隔的名称来定义。所有参数均按值参数调用。数组在参数定义中用符号“ name [] ”指定。在函数调用中,实际参数是数字参数的完整表达式。传递数组和定义数组参数使用相同的符号。命名数组按值传递给函数。由于函数定义是动态的,因此在调用函数时会检查参数编号和类型。参数数量或类型的任何不匹配都将导致运行时错误。调用未定义函数也会发生运行时错误。

AUTO_LIST是那些对“本地”使用变量的可选列表。自动列表的语法(如果存在)为“ 自动名称,...; ”。分号是可选的。每个名字是自动变量的名称。可以使用与参数中相同的符号来指定数组。这些变量的值在函数开始时被压入堆栈。然后将变量初始化为零,并在整个函数执行过程中使用它们。在函数退出时,将弹出这些变量,以便恢复这些变量的原始值(在函数调用时)。参数实际上是自动变量,它们被初始化为函数调用中提供的值。自动变量与传统的局部变量不同,因为如果函数A调用函数B,则B可以仅使用相同的名称访问函数A的自动变量,除非函数B称它们为自动变量。因为该自动变量和参数被压入堆栈,所以bc支持递归函数。

函数主体是bc语句的列表。同样,语句之间用分号或换行符分隔。Return语句导致函数终止并返回值。return语句有两种版本。第一种形式“ return ”将值0返回给调用表达式。第二种形式“ return(expression) ”计算表达式的值,并将该值返回给调用表达式。每个函数的末尾都有一个隐含的“ return(0) ”,它允许函数终止并返回0,而无需显式的return语句。

函数还更改变量ibase的用法。函数主体中的所有常量将在函数调用时使用ibase的值进行转换。在执行函数期间,ibase的更改将被忽略,但标准函数读取除外,它将始终使用ibase的当前值进行数字转换。

一些扩展已添加到功能。首先,定义的格式已经稍微放松了。该标准要求开括号与define关键字位于同一行,而所有其他部分必须位于以下行。较新版本的bc允许在函数的大括号之前和之后的任意数量的换行符。例如,以下定义是合法的。

define d (n) { return (2*n); } define d (n) { return (2*n); }

函数可以定义为voidvoid函数不返回任何值,因此可能无法在需要该值的任何地方使用。当在输入线上被自己调用时,void函数不会产生任何输出。关键字void放置在关键字定义和功能名称之间。例如,考虑以下会话。

define py (y) { print "--->", y, "<---", "0; }
define void px (x) { print "--->", x, "<---", "0; }
py(1)
--->1<---
0
px(1)
--->1<---

由于py不是void函数,因此对py(1)的调用将打印所需的输出,然后打印第二行,即该函数的值。由于未提供显式return语句的函数的值为零,因此将打印零。对于px(1),不会打印零,因为该函数是void函数。

此外,增加了对数组的变量调用。要通过变量array声明调用,函数定义中的array参数的声明类似于“ * name [] ”。对函数的调用与按值数组调用相同。

数学库

如果使用-l选项调用bc,则会预先加载数学库,并且默认比例设置为20。数学函数会将其结果计算为调用时设置的比例。数学库定义以下功能:

  • s (x) - 的正弦X,以弧度表示。
  • c (x) - 的余弦值X,以弧度表示。
  • a (x) - 的反正切X,以弧度表示。
  • l (x) - 的自然对数X。
  • e (x) - 将e提高到x的指数函数。
  • j (n,x) - x的整数阶n的Bessel函数。
bc [ -hlwsqv ] [long-options] [ file ... ]

Options

-h--help

Print a help message and exit.

-i--interactive

Force interactive mode.

-l--mathlib

Define the standard math library.

-w--warn

Give warnings for extensions to POSIX bc.

-s--standard

Process exactly the POSIX bc language.

-q--quiet

Do not print the normal GNU bc welcome message.

-v--version

Print the version number and Copyright information, and exit.

Numbers

The most basic element in bc is the number. Numbers are arbitrary-precision numbers. This precision is both in the integer part and the fractional part. All numbers are represented internally in decimal and all computation is done in decimal. Some versions of bc truncate results from divide and multiply operations.

There are two attributes of numbers, the length and the scale. The length is the total number of significant decimal digits in a number and the scale is the total number of decimal digits after the decimal point. For example:

.000001 has a length of 6 and scale of 6.

1935.000 has a length of 7 and a scale of 3.

Variables

Numbers are stored in two types of variables: simple variables and arrays. Both simple variables and array variables are named. Names begin with a letter followed by any number of letters, digits and underscores. All letters must be lowercase. Full alphanumeric names are an extension. In POSIX bc all names are a single lower case letter. The type of variable is clear by the context because all array variable names will be followed by brackets ([]).

There are four special variables: scaleibaseobase, and last.

scale defines how some operations use digits after the decimal point. The default value of scale is 0.

ibase and obase define the conversion base for input and output numbers. The default for both input and output is base 10.

last (an extension) is a variable that has the value of the last printed number.

All variables may have values assigned to them, and can be used in expressions.

Comments

Comments in bc start with the characters "/*" and end with the characters "*/". Comments may start anywhere and appear as a single space in the input. This causes comments to delimit other input items. For example, a comment can not be placed in the middle of a variable name. Comments include any newlines (end of line) between the start and the end of the comment.

To support the use of scripts for bc, a single line comment has been added as an extension. A single line comment starts at a "#" character and continues to the next end-of-line. The end-of-line character is not part of the comment and is processed normally.

Expressions

Numbers are manipulated by expressions and statements. Since the language was designed to be interactive, statements and expressions are executed as soon as possible. There is no "main" program; instead, code is executed as it is encountered. Functions, discussed in detail later, are defined when encountered.

A simple expression is just a constant. bc converts constants into internal decimal numbers using the current input base, specified by the variable ibase. There is an exception in functions. The legal values of ibase are 2 through 16. Assigning a value outside this range to ibase will result in a value of 2 or 16. Input numbers may contain the characters 0-9 and A-F. Note: They must be capital letters. Lowercase letters are reserved for variable names. Single-digit numbers always have the value of the digit regardless of the value of ibase. For multi-digit numbers, bc changes all input digits greater or equal to ibase to the value of ibase-1. This makes the number FFF always be the largest 3-digit number of the input base.

Full expressions are similar to other high-level languages. Since there is only one kind of number, there are no rules for mixing variable types. Instead, there are rules on the scale of expressions. Every expression has a scale that is derived from the scale of original numbers, the operation performed, and in many cases, the value of the variable scale. Legal values of the variable scale are 0 to the maximum number representable by a C integer.

In the following descriptions of legal expressions, "expr" refers to a complete expression and "var" refers to a simple or array variable. A simple variable is just a name and an array variable is specified as name[expr].

Unless specifically mentioned the scale of the result is the maximum scale of the expressions involved.

- expr - The result is the negation of the expression.

++ var - The variable is incremented by one and the new value is the result of the expression.

-- var - The variable is decremented by one and the new value is the result of the expression.

var ++ - The result of the expression is the value of the variable and then the variable is incremented by one.

var -- - The result of the expression is the value of the variable and then the variable is decremented by one.

expr + expr - The result of the expression is the sum of the two expressions.

expr - expr - The result of the expression is the difference of the two expressions.

expr * expr - The result of the expression is the product of the two expressions.

expr / expr - The result of the expression is the quotient of the two expressions. The scale of the result is the value of the variable scale.

expr % expr - The result of the expression is the "remainder" and it is computed in the following way. To compute a%b, first a/b is computed to scale digits. That result is used to compute a-(a/b)*b to the scale of the maximum of scale+scale(b) and scale(a). If scale is set to zero and both expressions are integers this expression is the integer remainder function.

expr ^ expr - The result of the expression is the value of the first raised to the power of the second. The second expression must be an integer. If the second expression is not an integer, a warning is generated and the expression is truncated to get an integer value. The scale of the result is scale if the exponent is negative. If the exponent is positive the scale of the result is the minimum of the scale of the first expression times the value of the exponent and the maximum of scale and the scale of the first expression. (e.g., scale(a^b) = min(scale(a)*b, max(scale, scale(a))).) It should be noted that expr^0 will always return the value of 1.

( expr ) - This alters the standard precedence to force the evaluation of the expression.

var = expr - The variable is assigned the value of the expression.

var = expr - This expression is equivalent to "var = varexpr" with the exception that the "var" part is evaluated only once. This can make a difference if "var" is an array.

Relational expressions are a special kind of expression that always evaluate to 0 or 1: 0 if the relation is false and 1 if the relation is true. These may appear in any legal expression. POSIX bc requires that relational expressions are used only in ifwhile, and for statements and that only one relational test may be done in them. The relational operators are:

expr1 < expr2

The result is 1 if expr1 is strictly less than expr2.

expr1 <= expr2

The result is 1 if expr1 is less than or equal to expr2.

expr1 > expr2

The result is 1 if expr1 is strictly greater than expr2.

expr1 >= expr2

The result is 1 if expr1 is greater than or equal to expr2.

expr1 == expr2

The result is 1 if expr1 is equal to expr2.

expr1 != expr2

The result is 1 if expr1 is not equal to expr2.

Boolean operations are also legal. (POSIX bc does NOT have boolean operations). The result of all boolean operations are 0 and 1 (for false and true) as in relational expressions. The boolean operators are:

!expr

The result is 1 if expr is 0.

expr && expr

The result is 1 if both expressions are non-zero.

expr || expr

The result is 1 if either expression is non-zero.

The expression precedence is as follows: (lowest to highest)

  • || operator, left associative
  • && operator, left associative
  • ! operator, nonassociative
  • Relational operators, left associative
  • Assignment operator, right associative
  • + and - operators, left associative
  • */ and % operators, left associative
  • ^ operator, right associative
  • unary - operator, nonassociative
  • ++ and -- operators, nonassociative

This precedence was chosen so that POSIX-compliant bc programs will run correctly. This will cause the use of the relational and logical operators to have some unusual behavior when used with assignment expressions. Consider the expression:

a = 3 < 5

Most C programmers would assume this would assign the result of "3 < 5" (the value 1) to the variable "a". What this does in bc is assign the value 3 to the variable "a" and then compare 3 to 5. It is best to use parenthesis when using relational and logical operators with the assignment operators.

There are a few more special expressions that are provided in bc. These have to do with user defined functions and standard functions. They all appear as "name(parameters)". See the section on functions for user defined functions. The standard functions are:

length ( expression )

The value of the length function is the number of significant digits in the expression.

read ( )

The read function (an extension) will read a number from the standard input, regardless of where the function occurs. Beware, this can cause problems with the mixing of data and program in the standard input. The best use for this function is in a previously written program that needs input from the user, but never allows program code to be input from the user. The value of the read function is the number read from the standard input using the current value of the variable ibase for the conversion base.

scale ( expression )

The value of the scale function is the number of digits after the decimal point in the expression.

sqrt ( expression )

The value of the sqrt function is the square root of the expression. If the expression is negative, a runtime error is generated.

Statements

Statements (as in most algebraic languages) provide the sequencing of expression evaluation. In bc, statements are executed "as soon as possible." Execution happens when a newline is encountered and there are one or more complete statements. Due to this immediate execution, newlines are important in bc. In fact, both a semicolon and a newline are used as statement separators. An improperly placed newline will cause a syntax error. Because newlines are statement separators, it is possible to hide a newline by using the backslash character. The sequence "\", where  is the newline, appears to bc as whitespace instead of a newline. A statement list is a series of statements separated by semicolons and newlines. The following is a list of bc statements and what they do: Things enclosed in brackets ([]) are optional parts of the statement.

expression

This statement does one of two things. If the expression starts with "...", it is considered to be an assignment statement. If the expression is not an assignment statement, the expression is evaluated and printed to the output. After the number is printed, a newline is printed. For example, "a=1" is an assignment statement and "(a=1)" is an expression that has an embedded assignment. All numbers that are printed are printed in the base specified by the variable obase. The legal values for obase are 2 through BC_BASE_MAX. (See the section "Limits.") For bases 2 through 16, the usual method of writing numbers is used. For bases greater than 16, bc uses a multi-character digit method of printing the numbers where each higher base digit is printed as a base 10 number. The multi-character digits are separated by spaces. Each digit contains the number of characters required to represent the base ten value of "obase-1". Since numbers are of arbitrary precision, some numbers may not be printable on a single output line. These long numbers will be split across lines using the "\" as the last character on a line. The maximum number of characters printed per line is 70. Due to the interactive nature of bc, printing a number causes the side effect of assigning the printed value to the special variable last. This feature allows the user to recover the last value printed without having to retype the expression that printed the number. Assigning to last is legal and will overwrite the last printed value with the assigned value. The newly assigned value will remain until the next number is printed or another value is assigned to last. Some installations may allow the use of a single period (.) which is not part of a number as a short hand notation for for last.

string

The string is printed to the output. Strings start with a double quote character and contain all characters until the next double quote character. All characters are take literally, including any newline. No newline character is printed after the string.

print list

The print statement (an extension) provides another method of output. The "list" is a list of strings and expressions separated by commas. Each string or expression is printed in the order of the list. No terminating newline is printed. Expressions are evaluated and their value is printed and assigned to the variable last. Strings in the print statement are printed to the output and may contain special characters. Special characters start with the backslash character (\). The special characters recognized by bc are "a" (alert or bell), "b" (backspace), "f" (form feed), "n" (newline), "r" (carriage return), "q" (double quote), "t" (tab), and "\" (backslash). Any other character following the backslash will be ignored.

{statement_list}

This option is the compound statement. It allows multiple statements to be grouped together for execution.

if (expression)statement1 [elsestatement2]

The if statement evaluates the expression and executes statement1 or statement2 depending on the value of the expression. If the expression is non-zero, statement1 is executed. If statement2 is present and the value of the expression is 0, then statement2 is executed. The else clause is an extension.

while ( expression )statement

The while statement will execute the statement while the expression is non-zero. It evaluates the expression before each execution of the statement. Termination of the loop is caused by a zero expression value or the execution of a break statement.

for ( [expression1] ; [expression2] ; [expression3] )statement

The for statement controls repeated execution of the statement. Expression1 is evaluated before the loop. Expression2 is evaluated before each execution of the statement. If it is non-zero, the statement is evaluated. If it is zero, the loop is terminated. After each execution of the statement, expression3 is evaluated before the reevaluation of expression2. If expression1 or expression3 are missing, nothing is evaluated at the point they would be evaluated. If expression2 is missing, it is the same as substituting the value 1 for expression2. The optional expressions are an extension. POSIX bc requires all three expressions. The following is equivalent code for the for statement:

expression1; while (expression2) { statement; expression3; }

break

This statement causes a forced exit of the most recent enclosing while statement or for statement.

continue

The continue statement (an extension) causes the most recent enclosing for statement to start the next iteration.

halt

The halt statement (an extension) is an executed statement that causes the bc processor to quit only when it is executed. For example, "if (0 == 1) halt" will not cause bc to terminate because the halt is not executed.

return

Return the value 0 from a function. (See the section on functions.)

return ( expression )

Return the value of the expression from a function. (See the section on functions.) As an extension, the parenthesis are not required.

Pseudo Statements

These statements are not statements in the traditional sense. They are not executed statements. Their function is performed at "compile" time.

limits

Print the local limits enforced by the local version of bc. (This is an extension.)

quit

When the quit statement is read, the bc processor is terminated, regardless of where the quit statement is found. For example, "if (0 == 1) quit" will cause bc to terminate.

warranty

Print a warranty notice. (This is an extension.)

Functions

Functions provide a method of defining a computation that can be executed later. Functions in bc always compute a value and return it to the caller. Function definitions are "dynamic" in the sense that a function is undefined until a definition is encountered in the input. That definition is then used until another definition function for the same name is encountered. The new definition then replaces the older definition. A function is defined as follows:

define name ( parameters ) { newline auto_list statement_list }

A function call is just an expression of the form "name(parameters)".

Parameters are numbers or arrays (an extension). In the function definition, zero or more parameters are defined by listing their names separated by commas. All parameters are call by value parameters. Arrays are specified in the parameter definition by the notation "name[]". In the function call, actual parameters are full expressions for number parameters. The same notation is used for passing arrays as for defining array parameters. The named array is passed by value to the function. Since function definitions are dynamic, parameter numbers and types are checked when a function is called. Any mismatch in number or types of parameters will cause a runtime error. A runtime error will also occur for the call to an undefined function.

The auto_list is an optional list of variables that are for "local" use. The syntax of the auto list (if present) is "auto name, ... ;". The semicolon is optional. Each name is the name of an auto variable. Arrays may be specified by using the same notation as used in parameters. These variables have their values pushed onto a stack at the start of the function. The variables are then initialized to zero and used throughout the execution of the function. At function exit, these variables are popped so that the original value (at the time of the function call) of these variables are restored. The parameters are really auto variables that are initialized to a value provided in the function call. Auto variables are different than traditional local variables because if function A calls function BB may access function A's auto variables by just using the same name, unless function B has called them auto variables. Because that auto variables and parameters are pushed onto a stack, bc supports recursive functions.

The function body is a list of bc statements. Again, statements are separated by semicolons or newlines. Return statements cause the termination of a function and the return of a value. There are two versions of the return statement. The first form, "return", returns the value 0 to the calling expression. The second form, "return ( expression )", computes the value of the expression and returns that value to the calling expression. There is an implied "return (0)" at the end of every function, which allows a function to terminate and return 0 without an explicit return statement.

Functions also change the usage of the variable ibase. All constants in the function body will be converted using the value of ibase at the time of the function call. Changes of ibase will be ignored during the execution of the function except for the standard function read, which will always use the current value of ibase for conversion of numbers.

Several extensions have been added to functions. First, the format of the definition has been slightly relaxed. The standard requires the opening brace be on the same line as the define keyword and all other parts must be on following lines. Newer versions of bc will allow any number of newlines before and after the opening brace of the function. For example, the following definitions are legal.

define d (n) { return (2*n); } define d (n) { return (2*n); }

Functions may be defined as void. A void function returns no value and thus may not be used in any place that needs a value. A void function does not produce any output when called by itself on an input line. The key word void is placed between the key word define and the function name. For example, consider the following session.

define py (y) { print "--->", y, "<---", "0; }
define void px (x) { print "--->", x, "<---", "0; }
py(1)
--->1<---
0
px(1)
--->1<---

Since py is not a void function, the call of py(1) prints the desired output and then prints a second line that is the value of the function. Since the value of a function that is not given an explicit return statement is zero, the zero is printed. For px(1), no zero is printed because the function is a void function.

Also, call by variable for arrays was added. To declare a call by variable array, the declaration of the array parameter in the function definition looks like "*name[]". The call to the function remains the same as call by value arrays.

Math Library

If bc is invoked with the -l option, a math library is preloaded and the default scale is set to 20. The math functions will calculate their results to the scale set at the time of their call. The math library defines the following functions:

  • s (x) - The sine of x, in radians.
  • c (x) - The cosine of x, in radians.
  • a (x) - The arctangent of x, in radians.
  • l (x) - The natural logarithm of x.
  • e (x) - The exponential function of raising e to the value x.
  • j (n,x) - The Bessel function of integer order n of x.

查看英文版

查看中文版

bc 例子

在sh中,以下代码将pi的值分配给shell变量pi。在这里,a表示反正切函数,它是使用-l选项加载的数学库的一部分:

pi=$(echo "scale=10; 4*a(1)" | bc -l)

以下是数学库中使用的指数函数的定义。该函数用POSIX bc编写。

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
  }
}

以下是使用bc的扩展功能实现用于计算支票簿余额的简单程序的代码。最好将该程序保存在文件中,以便可以多次使用它,而不必每次使用都重新键入它。

scale=2
print "\nCheck book program!\n"
print "  Remember, deposits are negative transactions.\n"
print "  Exit by a 0 transaction.\n\n"
print "Initial balance? "; bal = read()
bal /= 1
print "\n"
while (1) {
  "current balance = "; bal
  "transaction? "; trans = read()
  if (trans == 0) break;
  bal -= trans
  bal /= 1
}
quit

以下是递归阶乘函数的定义。

define f (x) { if (x <= 1) return (1); return (f(x-1) * x); }

In sh, the following code will assign the value of pi to the shell variable pi. Here, a refers to the arctangent function, which is part of the math library loaded with the -l option:

pi=$(echo "scale=10; 4*a(1)" | bc -l)

The following is the definition of the exponential function used in the math library. This function is written in POSIX bc.

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
  }
}

The following is code that uses the extended features of bc to implement a simple program for calculating checkbook balances. This program is best kept in a file so that it can be used many times without having to retype it at every use.

scale=2
print "\nCheck book program!\n"
print "  Remember, deposits are negative transactions.\n"
print "  Exit by a 0 transaction.\n\n"
print "Initial balance? "; bal = read()
bal /= 1
print "\n"
while (1) {
  "current balance = "; bal
  "transaction? "; trans = read()
  if (trans == 0) break;
  bal -= trans
  bal /= 1
}
quit

The following is the definition of the recursive factorial function.

define f (x) { if (x <= 1) return (1); return (f(x-1) * x); }

查看英文版

查看中文版

其他命令行

basename | bdiff | bfs | bg | biff | bs | break |

如此好文,分享给朋友
发表评论
验证码:
评论列表
共0条