BC(1)

NAME
bc - an arbitrary precision calculator language

SYNOPSIS
Run a bc program from FILE

        bc [-bdiqswy] FILE...

Start an interactive bc session

        bc [-bdiqswy]

DESCRIPTION
This is the PerlPowerTools implementation of the GNU version of bc, a standard calculator language. This is documented at:

https://www.gnu.org/software/bc/manual/html_mono/bc.html

  Options

•   -b - use Math::BigFloat

•   -d - turn on debugging output

•   -l - use mathlib

•   -y - turn on parser debugging output

  Environment
There are no environment variables that affect this program.

The bc language
NOTE: Some of this documentation is lifted straight from the GNU documentation for its version of bc.

"bc" is a language that supports arbitrary precision numbers with interactive execution of statements. There are some similarities in the syntax to the C programming language.

"bc" starts by processing code from all the files listed on the command line in the order listed. If no files are listed, then stdin is read. If a file contains a command to halt the processor, "bc" will never read from the standard input.

Dash ('-') is a pseudo-filename which represents stdin. This makes it possible to do something like "bc fileA - fileB" and have bc run commands from fileA before prompting for input, and then run commands from fileB after interactive input is finished.

"bc" will terminate interactive input via stdin if you enter "quit" or press "CTRL-C".

BASIC ELEMENTS

  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.

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, while 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 lower case.

The type of variable is clear by the context because all array variable names will be followed by brackets ( [ ] ).

  Special Variables

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

"ibase"
    Defines the conversion base for input numbers. Defaults to 10.

"obase"
    Defines the conversion base for output numbers. Defaults to 10.

  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. Note that this causes comments to delimit other input items, therefore a comment cannot be included 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 the 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.

A simple expression is just a constant. "bc" converts constants into internal decimal numbers using the current input base, specified by the variable "ibase".

Full expressions are similar to many other high level languages. Since there is only one kind of number, there are no rules for mixing types. Instead, there are rules on the scale of expressions. Every expression has a scale. This is derived from the scale of original numbers, the operation performed and in many cases, the value of the variable "scale".

  Basic Expressions
In the following descriptions of legal expressions, "expr" refers to a complete expression and "VAR" refers to a simple or an 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 second.

    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 op= expr"
    This is equivalent to "VAR = VAR op expr" with the exception that the "VAR" part is evaluated only once. This can make a difference if "VAR" is an array.

  Relational Expressions
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 "if", "while", 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 Expressions
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.

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

        = += etc     operators (assignment)  right associative
        ||           OR operator             left associative
        &&           AND operator            left associative
        !            NOT operator            nonassociative
        < > etc      relational operators    left associative
        + and -      operators               left associative
        *, / and %   operators               left associative
        ^            operator (power)        right associative
        unary -      operator                nonassociative
        ++ and --    operators               nonassociative

This differs from POSIX-compliant "bc", which puts assignment between relational operators and addition/subtraction. As a result, expressions behave more like they do in most languages (including perl and C).

  Special Expressions
There are a few more special expressions that are provided in "bc". These have to do with user-defined functions and standard functions. These are:

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

"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 run time 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 is one or more complete statements. Due to this immediate execution, newlines are very 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 "\<nl>" (where <nl> represents a newline your typed) appears to "bc" as whitespace instead of an actual 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 "<variable> <assignment> ...", 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.

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 taken 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 include:

            \a  alert or bell
            \b  backspace
            \f  form feed
            \n  newline
            \r  carriage return
            \q  double quote
            \t  tab
            \e  backslash.

    Any other character following a backslash will be ignored.

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

"if" ( EXPRESSION ) STATEMENT
    The "if" statement evaluates the expression and executes STATEMENT depending on the value of the expression. If the expression is non-zero, STATEMENT is executed. Otherwise it isn't. (The statement can be a block enclosed in { }.)

"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.

"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.

EXAMPLE
The following illustrates how "bc" expressions can be written in script form and fed to "bc" via stdin.

        print "\nCompute balances after withdrawals\n"

        bal = 100.00
        withdrawal = 20.00;

        while (1) {
                print "Balance: ", "\t", bal, "\n"
                print "Withdrawal: ", "\t", withdrawal, "\n"
                if ( (bal - withdrawal) < 0 ) break;
                bal -= withdrawal
        }

        print "Balance:", bal

        quit

BUGS AND LIMITATIONS
This implementation of "bc" is mostly POSIX compliant and has similar extensions to GNU "bc". However, some features and extensions are either not supported or are not working.

Perhaps the biggest non-working feature would be Function definitions via the "define" syntax, which if used generates syntax errors. As a consequence, the -l option (to load math library definitions) doesn't work either.

Setting the following variables don't seem to have the intended effects:

        scale
        ibase
        obase

Hexadecimal values, for use when ibase is > 10, are not supported.

Old style assignment operators (=+, =-, =*, =/, =%, =^) are not required to be supported by the POSIX standard, and they are not supported by this implementation. However, they will not generate any errors. Instead you will get a result you don't expect. For example:

        v=3; v += 2  # v is 5 as you would expect
        v=3; v =+ 2  # v is 2 because the 2nd expression is seen as v = +2

COMPARISON TO GNU "bc" AND OTHERS
The following "bc" features are not supported in this implementation. (Some are syntactically accepted, but simply return zero).

        * -w, --warn option
        * -s, --standard option
        * -q, --quiet option
        * -v, --version option
        * long options (e.g. --help)
        * LC_ language and NLSPATH environment variables
        * "last" special variable
        * "if" statement: "else" clause
        * "read" function
        * "continue" statement
        * "halt" statement
        * "limits" pseudo statement
        * "warranty" pseudo statement
        * function definitions

In addition, the GNU implementation set the precedence of assignment below + and - and above relational operators (< > etc). This implementation seems to make it the lowest precedence (i.e. below ||), as most perl (and C) users would expect.

REFERENCES
POSIX "bc" <https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html>

GNU "bc" <https://www.gnu.org/software/bc/manual/html_mono/bc.html>

  GNU's mathlib
Load the GNU math extensions with the "-l" switch:

        % bc -l FILE

The library provides these functions:

•   a(x) - the arctangent of X, where X is expressed in radians

•   c(x) - the cosine of X, where X is expressed in radians

•   e(X) - the natural base, e, raised to the X power

•   j(n,x) - the Bessel function of order n, where n is an integer

•   l(X) - the natural logarithm of X

•   s(x) - the sine of X, where X is expressed in radians

AUTHOR
Philip A. Nelson originally translated GNU bc to Perl for the PerlPowerTools project.

https://github.com/briandfoy/PerlPowerTools

LICENSE
You can use and modify this program under the terms of the GNU Public License version 2. A copy of this license is in the PerlPowerTools repository:

        https://github.com/briandfoy/PerlPowerTools/