- NUMBERS are arbitrary precision in both the integer and the fractional parts,
are represented internally in decimal , all computations are done in decimal.
Attributes :
length
: number of significant digits
scale
: number of digits after the dot. Default:0̸!
For example:
1.23456
has a length of 6 and scale of 5.
1234.567
has a length of 7 and a scale of 3.
- Input digits: 0̸-
9
,A
-F
. (NOT lowercase, which are variables).
- Single digit numbers are the same regardless of the value of
ibase
. (i.e. A
= 10̸.)
- Multi-digit numbers, with digits greater or equal to
ibase
, are assigned the value of ibase
-1 to each digit,
if ibase
=10̸, num=FF8CB
assigns 99899
to num.
- There is only one type of number.
- VARIABLES
Are set to zero upon first reference, names begin with a lowercase letter followed by letters, digits and underscores
POSIX names are a single lower case letter.
- Simple:
a, f, x1, y, index23
, loop_counter
, x
- Arrays: variable name followed by brackets
[ ]
.
- Special variables:
- COMMENTS:
/*
and */
surround a comment, may start anywhere,
acts as a single space in the input,
delimit other input items, can be multi-line.
#
begins a comment which continues to the end of line.
- EXPRESSIONS and STATEMENTS
Executed when end-of-line is encountered.
- expr negation of expr .
| ++var var is incremented by one, the new value is the result
| --var var is decremented by one, the new value is the result
| var++ The result is the value of var , then var is incremented by one.
| var-- The result is the value of var , then var is decremented by one.
| expr + expr | sum
| expr - expr | difference
| expr * expr | product
| expr / expr | divide. The scale of the result is scale !
>>> scale =2; 1/3
.33
>>> scale=7: 1/3
.3333333
>>> 1/2;
.5000000
>>> scale=2; 1/2
.50
| expr 1 % expr 2 | remainder computed by:
expr 1/expr 2 is computed to scale digits.
- That result is used to compute
expr 1-(expr 1/expr 2)
*expr 2
to the scale of the maximum of
scale+scale(expr2) and scale(expr1)
If scale is zero and both expr essions are integers this is the integer remainder
>>> 21%3
0
>>> 21%4 21/4 =5; 4*5=20; 21-20=1
1
>>> 21%5 21/5 =4; 5*4=20; 21-20=1
1
>>> 21%6 21/6 =3; 6*3=18; 21-18=3
3
>>> 21%7
0
>>>
>>> 21%8 21/8 =2; 8*2=16; 21-16=5
5
>>> 21%8.00
5.00
>>> 21%9 21/9 =2; 9*2=18; 21-18=3
3
>>> 21%9.00
3.00
>>> 21%9.100
2.800
>>> 21%9.110
2.780
expr ^ Iexprx | expr raised to the
integer Iexprx .
If Iexprx is negative: the scale of the result is scale .
If Iexprx is positive the scale of the result is the minimum of
- the scale of
expr times the value of the exponent and
- the maximum of
scale the scale of expr .
i.e : scale(a^b) = min(scale(a)*b, max( scale, scale(a))) .
Iexpr x ^0 returns 1
( expr ) | alters precedence
| var = expr | assignment
| var op= expr
example:
sum += entry equivalent to "var = var op expr " .
var is evaluated only once. This can make a difference if var is an array.
| | | | | | | | |
Relational expressions may appear in an 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.)
Relational operators
|
| result is 1 (true) if
expr1 < expr2 expr1 is strictly less than expr2.
| expr1 <= expr2 expr1 is less than or equal to expr2.
| expr1 > expr2 expr1 is strictly greater than expr2.
| expr1 >= expr2 expr1 is greater than or equal to expr2.
| expr1 == expr2 expr1 is equal to expr2.
| expr1 != expr2 expr1 is not equal to expr2.
| Boolean operators
(POSIX bc does NOT have boolean operations).
| !expr 1 if expr equals 0; 0 if expr is non-zero
| expr && expr both expr1 and expr2 are non-zero.
| expr1 || expr2 either expr1 or expr2 is non-zero.
| | | | | | | | | | |
Expression precedence (highest to lowest)
++ -- nonassociative |
Using relational and logical operators with assignment expressions evaluate differently than in many other languages.
Consider the expression:
a = 3 < 5
This assigns the value 3 to a and then compares 3 to 5 which outputs 1.
Most programmers expect the result of "3 < 5" (the value 1 (true)) is assigned to a .
Use parenthesis when using relational and logical operators with the assignment operators.
| - † nonassociative
| ^ right associative
| | left associative
| + - left associative
|
= += -= …† | right associative ‡
|
< <= > …† left associative ‡
! nonassociative
| && left associative
| || left associative
| | | | | | | | | |
The bitwise (and, or, xor , shift) , boolean and conditional operators:
& | ^ && || << >>
&= |= ^= &&= ||= <<= >>=
?:
Are not available. Use easyOnLineConverter.com
- FUNCTIONS
appears as "name(parameters)".
read ( ) read a value from standard input .
| length ( expression ) number of significant digits .
| scale ( expression ) number of digits after the dot (same as special variable scale ).
scale=5
1/2
.50000
scale(1/2)
5
scale(1/3)
5
scale(.5)
1
| sqrt ( expression ) square root. If the expression is negative, a run time error is generated.
Runtime error (func=(main), adr=4): Square root of a negative number
| | | | |
User defined functions provide a method of defining a computation that can be executed later which return a value to the caller.
A function definition :
define name ( [parameter[, …] ] ) { 
[ auto name [ , … ]] ; statement_list }
A function call:
name(parameters).
Parameters can be numbers or arrays. Numbers are call_by value (i.e. cannot be changed within the function).
Arrays are only call_by variable. Arrays are specified in the parameter definition by the notation name[]
.
In the function call, 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 variable to the function.
Variables are global (i.e. function B can access variables in the main as well as in function A) unless included in
auto
list.
Auto variables have their current values pushed onto a stack at the start of the function, 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 auto variables that are initialized to a value provided in the function call.)
Auto variables are sub-call accessable, i.e. if function A calls function B, B may access function A's auto variables, unless
function B has declared them auto variables.
Constants in the function body will be converted using the value of ibase
at the time of the call.
Changes to ibase
will be ignored during the execution of the function except for read()
, which
will uses the current value of ibase
for conversion of numbers.
Function definitions are "dynamic" i.e. a function is undefined until a definition is encountered (aka no forward referencing).
That definition is used until another definition function for name
is encountered.
- STATEMENTS
Execution ocurs when a newline is encountered with one or more complete statements.
Semicolon and a newline are statement separators. A trailing \
continutes a statment.
expression |
- If the expression starts with
variable assignment it is an assignment statement.
- If the expression is not an assignment statement, the expression is evaluated and output followed by .
For example-
a=1 is an assignment statement (no output is produced).
-
(a=1) is an expression that has an embedded assignment and the result is output.
All numbers are output in the base specified by obase which can range from 2 through BC_BASE_MAX.
Some numbers may not be outputable on a single output line and will be split with \ .
Outputing a number assigns the value the the special variable last
Some implementations permit dot (. ) (which is not part of a number) for last .
"string" string is output. No newline is appended.
| print list
list is a list of strings and expressions separated by commas. No newline is appended.
Expressions are evaluated, their value is printed and assigned to last .
Strings may contain:
\a (alert or bell), \b (backspace), \f (form feed), \n (newline),
\r (carriage return), \q (quotes, i.e. " ), \t (tab), and \\ (backslash).
| { statement_list } A compound statement, allows multiple statements
to be grouped together.
| if ( expression ) statement1 [else statement2]
|
Evaluates expression and
if expression is non-zero, statement1 is executed.
if expression is 0, then statement2 is executed.
| while ( expression ) statement
| | execute statement while expression is non-zero.
It evaluates expression before each execution of statement.
Termination of the loop is caused by a zero expression value or the execution of a break
| for ( [expression1] ; [expression2] ;
[expression3] ) statement
| | Controls repeated execution of statement.
expression1 is evaluated before the loop.
expression2 is evaluated before each execution of statement,
if non-zero, statement is evaluated.
If it is zero, the loop is terminated.
After each execution of 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 .
(POSIX bc requires all three expressions.)
| break exits the most recent enclosing while or for .
| continue causes the most recent enclosing for to start the next iteration.
| halt causes bc to quit
Note: if (0 == 1) halt will not cause bc to terminate because the halt is not executed.
| return ( expression ) Return the value of the expression from a function, default 0̸ .
| PSEUDO STATEMENTS
| limits display limits of the local version . an extension.
BC_BASE_MAX = 2147483647
BC_DIM_MAX = 65535
BC_SCALE_MAX = 2147483647
BC_STRING_MAX = 2147483647
MAX Exponent = 9223372036854775807
Number of vars = 32767
| quit
| warranty outputs version and a long non-warranty notice.
| | | | | | | | | | | | |
|
Due to the fact that auto variables and parameters are pushed onto a stack, bc supports recursive functions.
- MATH LIBRARY
If bc is invoked with --mathlib
, a math library is loaded and
the default scale
is set to 20.
s (r)
sine of r, r is in radians.
c (r)
cosine of r, r is in radians.
a (x)
arctangent of x, arctangent returns radians.
l (x)
natural logarithm of x.
e (x)
exponential function of raising e to the value x.
j (n,x)
bessel function of integer order n of x.
- EXAMPLES
In /bin/sh, the following will assign the value of "pi" to the shell variable $pi
using acrtan of 1.
pi=$(echo "4*a(1)" | /usr/bin/bc -l) # i.e. arcTan(1 radian) π/4
echo $pi
3.14159265358979323844
The exponential function used in the math library, 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
}
}
Use extended features 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
Definition of the recursive factorial function.
define f (x) {
if (x <= 1) return (1);
return (f(x-1) * x);
}
a=(1/3)^-1
scale=4
a
3.0003
scale=5
a
3.00003
- ReadLine
bc can be compiled with readline
input editor library.
Allows for a history of previous lines typed recallable, editable and searchable.
The special variable, history
is the number of lines of
history retained. The default, -1 unlimited, 0 disables the history.
Differences & extensions
There exists GNU bc, man
, brew install although it does not seem to have any(much) additional functionallity.
A single process which parses and runs a byte code translation of the program.
-c outputs the byte code, for debugging the parser and preparing the math library.
|
LANG | not conform POSIX processing of the LANG environment variable and all environment
variables starting with LC_ .
|
names | Traditional and POSIX bc have single letter names for functions,
variables and arrays. They have been extended to be multi-character names that start with a letter and may contain letters,
numbers and the underscore character.
|
Strings | Strings are not allowed to contain NUL characters. POSIX: all characters must be included in strings.
|
last | POSIX bc does not have a last variable. Some implementations use the period (.) .
|
comparisons |
POSIX allows comparisons only in the if and while
statements, and the second expression of the for statement.
Only one relational operation is allowed in each of those statements.
|
if statement, else clause POSIX bc does not have an else clause.
| for statement POSIX bc requires all expressions to be present in the for statement.
| &&, ||, ! POSIX bc does not have logical operators. , read function, print or continue statement
| array parameters | POSIX bc does not (currently) support array parameters in full.
The POSIX grammar allows for arrays in function definitions, but
does not provide a method to specify an array as a parameter.
Traditional implementations of bc have only call by value array parameters.
| =+, =-, =*, =/, =%, =^
POSIX bc does not require these "old style" assignment operators
to be defined. This version may allow these "old style" assignments. Use the limits statement to see if the installed version
supports them. If it does support the "old style" assignment
operators, the statement "a =- 1" will decrement a by 1 instead of setting a to the value -1.
| spaces in numbers | Not allowed. In some implementations, "x=1 3" assigns 13 to x.
| errors and execution |
The code will be executed when syntax and other errors are found in the program.
If a syntax error is found in a function definition, error recovery tries to find the beginning of a
statement and continue to parse the function.
Once a syntax error is found in the function, the function will not be
callable and becomes undefined.
Syntax errors in the interactive execution code will invalidate the current execution block.
The execution block is terminated by an end of line that appears after a complete sequence of statements. For example,
a = 1
b = 2
has two execution blocks and
{ a = 1
b = 2 }
has one execution block.
Any runtime error will terminate the execution of the current execution block. A runtime warning will not terminate the current execution block.
| | | | |
Interrupts
During an interactive session, the SIGINT signal (usually generated by the control-C character from the terminal) will cause
execution of the current execution block to be interrupted.
It will display a "runtime" error indicating which function was
interrupted. After all runtime structures have been cleaned up,
a message will be printed to notify the user that bc is ready
for more input. All previously defined functions remain defined
and the value of all non-auto variables are the value at the
point of interruption. All auto variables and function parameters are removed during the clean up process.
During a non interactive session, SIGINT terminates .
LIMITS
limits
statment:
BC_BASE_MAX = 2147483647 0x7FFFFFF
BC_DIM_MAX = 65535
BC_SCALE_MAX = 2147483647
BC_STRING_MAX = 2147483647
MAX Exponent = 9223372036854775807
Number of vars = 32767
BC_BASE_MAX maximum output base is currently set at 999. The maximum input base is 16.
| BC_DIM_MAX arbitrary limit of 65535 as distributed.
| BC_SCALE_MAX number of digits after the dot is limited to INT_MAX digits.
The number of digits before the dot is limited to INT_MAX digits.
| BC_STRING_MAX limit on the number of characters in a string is INT_MAX characters.
| exponent value of the exponent in the raise operation (^) is limited to LONG_MAX.
| multiply multiply routine may yield incorrect results if a number has
more than LONG_MAX / 90 total digits. For 32 bit longs, this number is 23,860,929 digits.
| code size Each function and the "main" program are limited to 16384 bytes of compiled byte code each. BC_MAX_SEGS can be changed to have more than 16 segments of 1024 bytes.
| variable names unique names for each of simple variables, arrays and functions.
| | | | | | | | |
ENVIRONMENT VARIABLES
$POSIXLY_CORRECTsame as -s
| $BC_ENV_ARGS | Format is the same as the command line arguments, processed first, so any files listed in the environent arguments
are processed before any command line argument files. This
allows the user to set up "standard" options and files to be processed at every invocation.
Files in the environment variables typically contain frequently used, custom function definitions.
| BC_LINE_LENGTH |
Length of an output line for numbers. includes the backslash and new line characters for long numbers.
| |
Files
Standard math library is usually from the file /usr/local/lib/libmath.b.
may be /lib/libmath.b.
)
This documents GNU bc version 1.04. , by Philip A. Nelson phil@cs.wwu.edu
The author would like to thank Steve Sommars (Steve.Sommars@att.com)
for his extensive help in testing the implementation. Many great suggestions were given. This is a much better product due to his involvement.