I'm using bc in Ubuntu Linux. It has a pre-defined constant PI that's set to 99. Why does bc define PI to be 99 instead of 3.14159...?
3 Answers
There is no built-in constant π in bc. If invoked with the -l option, some built-in functions become available, allowing you to evaluate π trigonometrically – the man page includes this example:
EXAMPLES
In the shell, the following will assign the value of π to the shell variable
pi.pi=$(echo "scale=10; 4*a(1)" | bc -l)
What is happening when you try to evaluate PI is the result of input base conversion, as described in the texinfo documentation for GNU bc (here version 1.07.1):
…
bcconverts constants into internal decimal numbers using the current input base, specified by the variableIBASE.
noting that
… For multi-digit numbers,
bcchanges all input digits greater or equal toIBASEto the value ofIBASE−1. This makes the numberZZZalways be the largest 3 digit number of the input base.
Correspondingly, in the default ibase=10, conversion of any pair of non-decimal digits results in decimal 99.
Earlier versions of GNU bc have a maximum ibase value of 16, and only make provision for characters in the set [0-9A-F]; characters outside of this range result in an error condition in that case.
You can see this the bc Command Manual version 1.06,
which also contains the above passages.
- 10,332
- 10
- 39
- 68
- 78,509
- 12
- 109
- 152
-
What version of `bc` is this? I don't get this behaviour on `bc 1.06.95`. Here, `PI` gives me two lines of error: `(standard_in) 1: illegal character: P` and `(standard_in) 1: illegal character: I`. Digging harder, it seems that your rule applies here only to the letters `A`-`F`, and even then only partly: `F` -> `15` (hex?) but `FF` -> `99` – roaima Feb 28 '22 at 14:17
-
2@roaima tested on GNU bc 1.07.1 – steeldriver Feb 28 '22 at 14:24
-
1Thanks. Definitely a change in behaviour, actual and (now that I read it) documented. In 1.06.95 the maximum value of `ibase` is 16, and your description involving `ZZZ` is here notated with `FFF`. – roaima Feb 28 '22 at 14:46
-
Thanks for the update @roaima I have added a note to that effect – steeldriver Feb 28 '22 at 16:16
I am not sure bc have Pi number internally, but you can always calculate it on this way:
4*a(1)
function a(x) is actualy arctangent
- 16,541
- 5
- 32
- 44
-
10This is even the first example in the “EXAMPLES” section of the man page: `echo "scale=10; 4*a(1)" | bc -l` (you need to specify `-l` to get the `a()` function). – Stephen Kitt Feb 28 '22 at 12:34
No, there is no (math) constant PI defined as 99 in (any) bc.
What is customary in bc is to interpret uppercase letters as constant numeric values. (Lowercase letters are variable names).
Even in POSIX it is a long standing concept that A means the decimal numerical value of 10:
When either ibase or obase is assigned a single digit value from the list in Lexical Conventions in bc, the value shall be assumed in hexadecimal. (For example, ibase=A sets to base ten, regardless of the current ibase value.).
That allows the reset of the input base to decimal 10 regardless of the base active at that point, that is: ibase=A always works to reset ibase to 10.
Depending on the version of bc in use, the following digits B thru Z might be defined to have some specific value, none, or generate an error.
In specific, for GNU bc version 1.07 the value of a single upper case letter goes up to 35 (no matter which IBASE has been set).
$ echo $(bc <<<'A;B;C;D;E;F;G;H;I;Z')
10 11 12 13 14 15 16 17 18 35
But for double, triple, etc uppercase digits the value is limited to be ibase-1.
$ echo $(bc <<<'AA;BB;GG;ZZ;AAA;ZZZ')
99 99 99 99 999 999
$ echo $(bc <<<'ibase=14;obase=ibase;AA;BB;GG;ZZ;AAA;ZZZ')
AA BB DD DD AAA DDD
Math PI
The value of the mathematical constant pi (or its usual symbol π) might be calculated with:
$ bc -l <<<'scale=40; 4*a(1)'
3.1415926535897932384626433832795028841968
Or, to set a variable:
bc -l <<<'scale=40; pi=4*a(1); pi'
3.1415926535897932384626433832795028841968