Provides an interpreter for arbitrary-precision arithmetic language.
The bc command is an interactive process that provides arbitrary-precision arithmetic. The bc command first reads any input files specified by the File parameter and then reads the standard input. The input files must be text files containing a sequence of commands, statements, or function definitions that the bc command can read and execute.
The bc command is a preprocessor for the dc command. It calls the dc command automatically, unless the -c (compile only) flag is specified. If the -c flag is specified, the output from the bc command goes to standard output.
The bc command allows you to specify an input and output base for operations in decimal, octal, or hexadecimal. The default is decimal. The command also has a scaling provision for decimal point notation. The bc command always uses the . (period) to represent the radix point, regardless of any decimal point character specified as part of the current locale.
The syntax for the bc command is similar to that of the C language. You can use the bc command to translate between bases by assigning the ibase keyword to the input base and the obase keyword to the output base. A range of 2-16 is valid for the ibase keyword. The obase keyword ranges from 2 up to the limit set by the BC_BASE_MAX value defined in the /usr/include/sys/limits.h file. Regardless of the ibase and obase settings, the bc command recognizes the letters A-F as their hexadecimal values 10-15.
The output of the bc command is controlled by the program read. Output consists of one or more lines containing the value of all executed expressions without assignments. The radix and precision of the output are controlled by the values of the obase and scale keywords.
Further information about the way in which the bc command processes information from a source file is described in the following sections:
Grammar
The following grammar describes the syntax for the bc program, where program stands for any valid program:
%token EOF NEWLINE STRING LETTER NUMBER
%token MUL_OP
/* '*', '/', '%' */
%token ASSIGN_OP
/* '=', '+=', '-=', '*=', '/=', '%=', '^=' */
%token REL_OP
/* '==', '<=', '>=', '!=', '<', '>' */
%token INCR_DECR
/* '++', '--' */
%token Define Break Quit Length
/* 'define', 'break', 'quit', 'length' */
%token Return For If While Sqrt
/* 'return', 'for', 'if', 'while', 'sqrt' */
%token Scale Ibase Obase Auto
/* 'scale', 'ibase', 'obase', 'auto' */
%start program
%%
program : EOF
| input_item program
;
input_item : semicolon_list NEWLINE
| function
;
semicolon_list : /* empty */
| statement
| semicolon_list ';' statement
| semicolon_list ';'
;
statement_list : /* empty */
| statement
| statement_list NEWLINE
| statement_list NEWLINE statement
| statement_list ';'
| statement_list ';' statement
;
statement : expression
| STRING
| Break
| Quit
| Return
| Return '(' return_expression ')'
| For '(' expression ';'
relational_expression ';'
expression ')' statement
| If '(' relational_expression ')' statement
| While '(' relational_expression ')' statement
| '{' statement_list '}'
;
function : Define LETTER '(' opt_parameter_list ')'
'{' NEWLINE opt_auto_define_list
statement_list '}'
;
opt_parameter_list:/* empty */
| parameter_list
;
parameter_list : LETTER
| define_list ',' LETTER
;
opt_auto_define_list
: /* empty */
| Auto define_list NEWLINE
| Auto define_list ';'
;
define_list : LETTER
| LETTER '[' ']'
| define_list ',' LETTER
| define_list ',' LETTER '[' ']'
;
opt_argument_list : /* empty */
| argument_list
;
argument_list : expression
| argument_list ',' expression
;
relational_expression
: expression
| expression REL_OP expression
;
return_expression : /* empty */
| expression
;
expression : named_expression
| NUMBER
| '(' expression ')'
| LETTER '(' opt_argument_list ')'
| '-' expression
| expression '+' expression
| expression '-' expression
| expression MUL_OP expression
| expression '^' expression
| INCR_DECR named_expression
| named_expression INCR_DECR
| named_expression ASSIGN_OP expression
| Length '(' expression ')'
| Sqrt '(' expression ')'
| Scale '(' expression ')'
;
named_expression : LETTER
| LETTER '[' expression ']'
| Scale
| Ibase
| Obase
;
Lexical Conventions
The following lexical conventions apply to the bc command:
NUMBER : integer
| '.' integer
| integer '.'
|integer '.' integer
;
integer : digit
| integer digit
;
digit : 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
| 8 | 9 | A | B | C | D | E | F
;
NUMBER token values are interpreted as
numerals in the base specified by the ibase internal register
value.auto for length return sqrt
break ibase obase scale while
define if quit
a b c d e f g h i j k l m n o p q r s t u v w x y z
Identifiers and Operators
There are three kinds of identifiers recognized by the bc command: ordinary identifiers, array identifiers, and function identifiers. All three types consist of single, lowercase letters. Array identifiers are followed by [ ] (left and right brackets). An array subscript is required except in an argument or auto list. Arrays are singly dimensioned and can contain up to the amount specified by the BC_DIM_MAX value. Indexing begins at 0. Therefore an array is indexed from 0 up to the value defined by BC_DIM_MAX -1. Subscripts are truncated to integers. Function identifiers must be followed by ( ) (left and right parentheses) and possibly by enclosing arguments. The three types of identifiers do not conflict.
The Operators in a bc Program table summarizes the rules for precedence and associativity of all operators. Operators on the same line have the same precedence. Rows are in order of decreasing precedence.
Operator | Associativity |
---|---|
++, - - | not applicable |
unary - | not applicable |
^ | right to left |
*, /, % | left to right |
+, binary - | left to right |
=, +=, -=, *=, /=, ^= | right to left |
==, <=, >=, !=, <, > | none |
Each expression or named expression has a scale, which is the number of decimal digits maintained as the fractional portion of the expression.
Named expressions are places where values are stored. Named expressions are valid on the left side of an assignment. The value of a named expression is the value stored in the place named. Simple identifiers and array elements are named expressions; they have an initial value of zero and an initial scale of zero.
The internal registers scale, ibase, and obase are all named expressions. The scale of an expression consisting of the name of one of these registers is 0. Values assigned to any of these registers are truncated to integers. The scale register contains a global value used in computing the scale of expressions (as described below). The value of the scale register is limited to 0 <= scale <= {BC_SCALE_MAX} and has a default value of 0. The ibase and obase registers are the input and output number radix, respectively. The value of ibase is limited to 2 <= ibase <= 16. The value of obase is limited to 2 <= obase = {BC_BASE_MAX}
When either the ibase or obase registers are assigned a single-digit value from the list described in "Lexical Conventions" , the value is assumed in hexadecimal. For example:
ibase=A
sets to base ten, regardless of the current ibase register value. Otherwise, the behavior is undefined when digits greater than or equal to the value of the ibase register appear in the input. Both ibase and obase registers have initial values of 10.
Internal computations are conducted as if in decimal, regardless of the input and output bases, to the specified number of decimal digits. When an exact result is not achieved, for example:
scale=0; 3.2/1
the bc command truncates the result.
All numerical values of the obase register are output according to the following rules:
0 1 2 3 4 5 6 7 8 9 A B C D E F
which represent the values 0 through 15, respectively.01 15 24
in base 125, as:
008 024
Expressions
A numeric constant is an expression. The scale is the number of digits that follow the radix point in the input representing the constant, or 0 if no radix point appears.
The sequence (expression) is an expression with the same value and scale as expression. The parentheses can be used to alter the normal precedence.
The unary and binary operators have the following semantics:
Item | Description |
---|---|
-expression | The result is the negative of the expression. The scale of
the result is the scale of the expression. The unary increment and decrement operators do not modify the scale of the named expression upon which they operate. The scale of the result is the scale of that named expression. |
++named_expression | The named expression is incremented by 1. The result is the value of the named expression after incrementing. |
- -named_expression | The named expression is decremented by 1. The result is the value of the named expression after decrementing. |
named_expression++ | The named expression is incremented by 1. The result is the value of the named expression before incrementing. |
named_expression- - | The named expression is decremented by 1. The result is the value of the named expression before decrementing. |
The exponentiation operator, ^ (caret), binds right to left.
Item | Description |
---|---|
expression ^expression | The result is the first expression raised to the power
of the second expression. If the second expression is not an
integer, the behavior is undefined. If a is the scale of
the left expression and b is the absolute value of the right
expression, the scale of the result is:
|
The multiplicative operators * (asterisk), / (slash), and % (percent) bind left to right.
Item | Description |
---|---|
expression * expression | The result is the product of the two expressions. If a and b are the scales of the two expressions, then
the scale of the result is:
|
expression / expression | The result is the quotient of the two expressions. The scale of the result is the value of scale. |
expression % expression | For expressions a and b, a % b is evaluated equivalent to the following steps:
|
The additive operators + (plus) and - (minus) bind left to right.
Item | Description |
---|---|
expression + expression | The result is the sum of the two expressions. The scale of the result is the maximum of the scales of the expressions. |
expression - expression | The result is the difference of the two expressions. The scale of the result is the maximum of the scales of the expressions. |
The following assignment operators bind right to left:
Item | Description |
---|---|
named-expression = expression | This expression results in assigning the value of the expression on the right to the named expression on the left. The scale of both the named expression and the result is the scale of the expression. |
The compound assignment forms:
named-expression <operator >= expression
are equivalent to:
named-expression = named-expression <operator > expression
except that the named expression is evaluated only once.
Unlike all other operators, the following relational operators are only valid as the object of an if or while statement or inside a for statement:
Item | Description |
---|---|
expression1 < expression2 | The relation is true if the value of expression1 is strictly less than the value of expression2. |
expression1 > expression2 | The relation is true if the value of expression1 is strictly greater than the value of expression2. |
expression1 <= expression2 | The relation is true if the value of expression1 is less than or equal to the value of expression2. |
expression1 >= expression2 | The relation is true if the value of expression1 is greater than or equal to the value of expression2. |
expression1 == expression2 | The relation is true if the values of expression1 and expression2 are equal. |
expression1 != expression2 | The relation is true if the values of expression1 and expression2 are unequal. |
Statements
When a statement is an expression, unless the main operator is an assignment, execution of the statement writes the value of the expression followed by a newline character.
When a statement is a string, execution of the statement writes the value of the string.
Statements separated by semicolons or newline characters are executed sequentially. In an interactive invocation of the bc command, each time a newline character is read that satisfies the grammatical production:
input_item : semicolon_list NEWLINE
the sequential list of statements making up the semicolon_list is executed immediately, and any output produced by that execution is written without any buffer delay.
If an if statement (if (relation) statement), the statement is executed if the relation is true.
The while statement (while (relation) statement) implements a loop in which the relation is tested. Each time the relation is true, the statement is executed and the relation retested. When the relation is false, execution resumes after statement.
A for statement (for (expression; relation; expression) statement) is the same as:
first-expression
while (relation) {
statement
last-expression
}
All three expressions must be present.
The break statement causes termination for a for or while statement.
The auto statement (auto identifier [,identifier ] ...) causes the values of the identifiers to be pushed down. The identifiers can be ordinary identifiers or array identifiers. Array identifiers are specified by following the array name by empty square brackets. The auto statement must be the first statement in a function definition.
The define statement:
define LETTER ( opt_parameter_list ) {
opt_auto_define_list
statement_list
}
defines a function named LETTER. If the LETTER function was previously defined, the define statement replaces the previous definition. The expression:
LETTER ( opt_argument_list )
invokes the LETTER function. The behavior is undefined if the number of arguments in the invocation does not match the number of parameters in the definition. Functions are defined before they are invoked. A function is considered defined within its own body, so recursive calls are valid. The values of numeric constants within a function are interpreted in the base specified by the value of the ibase register when the function is invoked.
The return statements (return and return(expression)) cause termination of a function, popping of its auto variables, and specify the result of the function. The first form is equivalent to return(0). The value and scale of an invocation of the function is the value and scale of the expression in parentheses.
The quit statement (quit) stops execution of a bc program at the point where the statement occurs in the input, even if it occurs in a function definition or in an if, for, or while statement.
Function Calls
A function call consists of a function name followed by parentheses containing a comma-separated list of expressions, which are the function arguments. A whole array passed as an argument is specified by the array name followed by [ ] (left and right brackets). All function arguments are passed by value. As a result, changes made to the formal parameters have no effect on the actual arguments. If the function terminates by executing a return statement, the value of the function is the value of the expression in the parentheses of the return statement, or 0 if no expression is provided or if there is no return statement.
The result of sqrt(expression) is the square root of the expression. The result is truncated in the least significant decimal place. The scale of the result is the scale of the expression or the value of scale, whichever is larger.
The result of length(expression) is the total number of significant decimal digits in the expression. The scale of the result is 0.
The result of scale(expression) is the scale of the expression. The scale of the result is 0.
There are only two storage classes in a bc program, global and automatic (local). Only identifiers that are to be local to a function need be declared with the auto keyword. The arguments to a function are local to the function. All other identifiers are assumed to be global and available to all functions. All identifiers, global and local, have initial values of 0. Identifiers declared as auto are allocated on entry to the function and released on returning from the function. Therefore they do not retain values between function calls. The auto arrays are specified by the array name followed by [ ] (left bracket, right bracket). On entry to a function, the old values of the names that appear as parameters and as automatic variables are pushed onto a stack. Until the function returns, reference to these names refers only to the new values.
References to any of these names from other functions that are called from this function also refer to the new value until one of those functions uses the same name for a local variable.
Functions in -l Math Library
The following functions are defined when you specify the -l flag:
Item | Description |
---|---|
s(expression) | Specifies the sine of expressionx, where expression is in radians. |
c(expression) | Specifies the cosine of expressionx, where expression is in radians. |
a(expression) | Specifies the arctangent of expressionx, where expression is in radians. |
l(expression) | Specifies the natural logarithm of expression. |
e(expression) | Specifies the exponential of expression. |
j(expression,expression) | Specifies the Bessel function of integer order. |
The scale of an invocation of each of these functions is the value of the scale keyword when the function is invoked. The behavior is undefined if any of these functions is invoked with an argument outside the domain of the mathematical function.
Item | Description |
---|---|
-c | Compiles the File parameter, but does not invoke the dc command. |
-l | (Lowercase L) Defines a library of math functions, and sets the scale variable to 20. |
This command returns the following exit values:
Item | Description |
---|---|
0 | Successful completion. |
1 | Encountered a syntax error or could not access the input file. |
unspecified | Any other error occurred. |
bc
1/4
displays only 0. To set the scale variable
and add a comment, enter: scale = 1 /* Keep 1 decimal place */
1/4
The screen displays 0.2. Entering: scale = 3 /* Keep 3 decimal places */
1/4
displays 0.250. Entering: 16+63/5
displays 28.600. Entering
(16+63)/5
displays 15.800. Entering 71/6
displays 11.833.The bc command displays the value of each expression when you press the Enter key, except for assignments.
When you enter the bc command expressions directly from the keyboard, press the End-of-File (Ctrl-D) key sequence to end the bc command session and return to the shell command line.
bc -l prog.bc
e(2) /* e squared */
ma
f(5) /* 5 factorial */
The screen displays 120. If you enter: f(10) /* 10 factorial */
The screen
displays 3628800.This sequence interprets the bc program saved in the prog.bc file, and reads more of the bc command statements from the keyboard. Starting the bc command with the -l flag makes the math library available. This example uses the e (exponential) function from the math library, and f is defined in the prog.bc program file as:
/* compute the factorial of n */
define f(n) {
auto i, r;
r = 1;
for (i=2; i<=n; i++) r =* i;
return (r);
}
The statement following a for or while statement must begin on the same line. When you enter the bc command expressions directly from the keyboard, press the End-of-File
(Ctrl-D) key sequence to end the bc command session and return
to the shell command line.bc -c
(a * b) % (3 + 4 * c)
lalb* 3 4lc*+%ps.
This sequence compiles the bc command infix-notation expression into an expression that the dc command can interpret. The dc command evaluates extended RPN expressions. In the compiled output, the l before each variable name is the dc subcommand to load the value of the variable onto the stack. The p displays the value on top of the stack, and the s. discards the top value by storing it in register . (dot). You can save the RPN expression in a file for the dc command to evaluate later by redirecting the standard output of this command. When you enter the bc command expressions directly from the keyboard, press the End-of-File (Ctrl-D) key sequence to end the bc command session and return to the shell command line.
x=$(printf "%s\n" 'scale = 10; 104348/33215' | bc)
The following bc program prints the same approximation of
pi, with a label, to standard output: scale = 10
"pi equals "
104348 / 33215
scale = 20
define e(x){
auto a, b, c, i, s
a = 1
b = 1
s = 1
for (i = 1; 1 == 1; i++){
a = a*x
b = b*i
c = a/b
if (c == 0) {
return(s)
}
s = s+c
}
}
To print approximate values of the exponential function
of the first 10 integers, enter: for (i = 1; i <= 10; ++i) {
e(i)
}
Item | Description |
---|---|
/usr/bin/bc | Contains the bc command. |
/usr/lib/lib.b | Contains the mathematical library. |
/usr/bin/dc | Contains the desk calculator. |