bc Command

Purpose

Provides an interpreter for arbitrary-precision arithmetic language.

Syntax

bc-c ] [  -l ] [ File ... ]

Description

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:

  1. The bc command recognizes the longest possible lexical token or delimiter beginning at a given point.
  2. Comments begin with /* (slash, asterisk) and end with */ (asterisk, slash). Comments have no effect except to delimit lexical tokens.
  3. The newline character is recognized as the NEWLINE token.
  4. The STRING token represents a string constant. The string begins with " (double quotation mark) and terminates with " (double quotation mark). All characters between the quotation marks are taken literally. There is no way to specify a string that contains " (double quotation mark). The length of each string is limited to the maximum bytes set in the BC_STRING_MAX value, which is defined in the limits.h file.
  5. Blank characters have no effect except as they appear in the STRING token or when used to delimit lexical tokens.
  6. The \n (backslash, newline) character:
    • delimits lexical tokens.
    • is interpreted as a character sequence in STRING tokens.
    • is ignored when part of a multiline NUMBER token.
  7. A NUMBER token uses the following grammar:
    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.
  8. The value of a NUMBER token is interpreted as a numeral in the base specified by the value of the ibase internal register. Each of the digit characters has the value from 0 to 15 in the order listed here, and the period character presents the radix point. The behavior is undefined if digits greater than or equal to the value of the ibase register appear in the token. There is an exception for single-digit values being assigned to the ibase and obase registers themselves.
  9. The following keywords are recognized as tokens:
    auto    for     length   return sqrt
    break   ibase   obase    scale  while
    define  if      quit
  10. Except within a keyword, any of the following letters are considered a LETTER token:
    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
  11. The following single-character and two-character sequences are recognized as the ASSIGN_OP token:
    • = (equal sign)
    • += (plus, equal sign)
    • -= (minus, equal sign)
    • *= (asterisk, equal sign)
    • /= (slash, equal sign)
    • %= (percent, equal sign)
    • ^= (caret, equal sign)
  12. The following single characters are recognized as the MUL_OP token:
    • * (asterisk)
    • / (slash)
    • % (percent)
  13. The following single-character and two-character sequences are recognized as the REL_OP token:
    • == (double equal sign)
    • <= (less than, equal sign)
    • >= (greater than, equal sign)
    • != (exclamation point, equal sign)
    • < (less than)
    • > (greater than)
  14. The following two-character sequences are recognized as the INCR_DECR token:
    • ++ (double plus sign)
    • -- (double hyphen)
  15. The following single characters are recognized as tokens. The token has the same name as the character:
    <newline>
    ( (left parenthesis)
    ) (right parenthesis)
    , (comma)
    + (plus)
    - (minus)
    ; (semicolon)
    [ (left bracket)
    ] (right bracket)
    ^ (caret)
    { (left brace)
    } (right brace)
  16. The EOF token is returned when the end of input is reached.

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:

  1. If the value is less than 0, output a - (hyphen).
  2. Output one of the following, depending on the numerical value:
    • If the absolute value of the numerical value is greater than or equal to 1, output the integer portion of the value as a series of digits appropriate to the obase register (described in step 3). Next output the most significant non-zero digit, followed by each successively less significant digit.
    • If the absolute value of the numerical value is less than 1 but greater than 0 and the scale of the numerical value is greater than 0, it is unspecified whether the character 0 is output.
    • If the numerical value is 0, output the character 0.
  3. If the scale of the value is greater than 0, output a . (period) followed by a series of digits appropriate to the following obase register values. The digits represent the most significant portion of the fractional part of the value, and s represents the scale of the value being output:
    • If the obase value is 10, output s number of digits.
    • If the obase value is greater than 10, output the number less than or equal to s.
    • If the obase value is less than 10, output a number greater than or equal to s.
    • For obase values other than 10, this should be the number of digits needed to represent a precision of 10s.
    • For obase values from 2 to 16, valid digits are the first obase of the single characters:
      0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
      which represent the values 0 through 15, respectively.
    • For bases greater than 16, each digit is written as a separate multidigit decimal number. Each digit except the most significant fractional digit is preceded by a single space character. For bases 17 to 100, the bc command writes two-digit decimal numbers, for bases 101 to 1000 the bc command writes three-digit decimal numbers. For example, the decimal number 1024 in base 25 would be written as:
      01 15 24

      in base 125, as:

      008 024
    Very large numbers are split across lines, with 70 characters per line in the POSIX locale. Other locales may split at different character boundaries. Lines that are continued must end with a \ (backslash).

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:
if b >= 0 min(a * b, max(scale, a))
if b <     0 scale

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:
min(a+b,max(scale,a,b))
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:
  1. Compute a/b to current scale.
  2. Use the result to compute:
    a - (a / b) * b
    to scale:
    max(scale + scale(b), scale(a))
    The scale of the result will be:
    max(scale + scale(b), scale(a))
When scale is zero, the % operator is the mathematical remainder operator.

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.

Flags

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.

Exit Status

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.

Examples

  1. You can use the bc command as a calculator. Depending on whether you set the scale variable and with what value, the system displays fractional amounts. Entering:
    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.

  2. To write and run a C-like program, enter a command similar to the following:

    bc  -l prog.bc
    e(2) /* e squared */
    ma

    The screen displays 7.38905609893065022723. If you enter:
    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.
  3. To convert an infix expression to Reverse Polish Notation (RPN), enter:

    bc  -c
    (a * b) % (3 + 4 * c)

    The screen displays:
    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.

  4. To assign in the shell an approximation of the first 10 digits of pi to the variable x, enter:
    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
  5. To define a function to compute an approximate value of the exponential function (such a function is predefined if the -l (lowercase L) option is specified), enter:
    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)
    }

Files

Item Description
/usr/bin/bc Contains the bc command.
/usr/lib/lib.b Contains the mathematical library.
/usr/bin/dc Contains the desk calculator.