bc(1)

명칭
bc - 임의 정밀도의 계산 언어

서식
bc [ -hlwsqv ] [long-options] [ file ... ]

버젼
이 메뉴얼은 GNU bc version 1.06 에 대해 기술되어 있습니다.

해설
bc 는, 임의의 정밀도의 수치를 취급할 수가 있어 프로그램 언어 C 의 문법으로 잘 닮은 형태의 입력을 대화적으로 실행하는 언어입니다. 명령행의 옵션의 지정에 의해, 표준 수학 프로그램 라이브러리를 사용하는 일도 할 수 있습니다. 이것을 지정했을 경우는, 어느 파일을 처리하는 것보다도 전에 수학 프로그램 라이브러리가 정의됩니다. bc 는 동작을 개시하면(자) 우선 최초로 명령행으로 지정한 파일을 순서에 처리합니다. 모든 파일을 처리한 후는, bc 는 표준 입력으로부터의 읽기를 실시합니다. 모든 코드는, 그것이 읽어 입 시점에서 실행되어 갑니다. (만약, 파일중에 프로세서를 멈춘다 명령이 포함되어 있었을 경우는, 표준 입력으로부터의 읽기는 행해지지 않습니다. )

본버젼의 bc 는, 전통적인 bc 의 실장 및 POSIX 의 드래프트 표준보다 확장되고 있습니다. 명령행 옵션에 의해, 이러한 확장에 대해서 경고를 표시하거나 거절하거나 하는 것이 가능합니다. 본문서에서는, 이 프로세서가 수리하는 언어에 대해 설명합니다. 확장 기능에 대해서는 그 취지 명기합니다.

  옵션

-h, --help
    사용 방법을 표시해, 종료합니다.

-i, --interactive
    대화 모드를 강제합니다.

-l, --mathlib
    표준 수학 프로그램 라이브러리를 정의합니다.

-w, --warn
    POSIX bc 에 대한 확장 기능이 입력되었을 경우는 경고를 냅니다.

-s, --standard
    POSIX bc 의 언어 사양에 엄밀하게 따라서 처리합니다.

-q, --quiet
    GNU bc 도입 메세지를 표시하지 않습니다.

-v, --version
    버젼 번호와 저작권을 표시해 종료합니다.

  수
bc 에 있어서의 가장 기본적인 요소는 `수'입니다. 수는, 정수부와 소수부가 있어, 임의의 정밀도를 취할 수가 있습니다. 모든 수는, 내부에서는 10 진수로 표현되고 있어 계산도 10 진수로 행해집니다. (본버젼에서는, 제산과 곱셈으로 결과에 잘라버림이 일어납니다. ) 수에는 length 와 scale 라고 하는 2 개의 속성이 있습니다. length 는 10 진에서의 유효 자리수로, scale 는 소수점 이하의 10 진에서의 유효 자리수입니다. 예를 들면,
     . 000001 은, length가 6 으로, scale 도 6 입니다.
     1935.000 은, length가 7 으로, scale 가 3 입니다.

  변수
수는, 단순 변수와 배열의 2 종류의 변수에 보존됩니다. 단순 변수와 배열 변수에는 모두 이름을 붙일 수 있습니다. 이 이름은, 최초의 1 캐릭터눈이 알파벳으로, 후는, 알파벳, 숫자 및 언더스코어를 임의의 캐릭터수 조합해 사용할 수가 있습니다. 모든 알파벳은 소문자가 아니면 안됩니다. (알파벳과 숫자를 사용한 이름의 기능은 확장 기능입니다. POSIX bc 에서는, 변수에 영소문자 1 캐릭터 밖에 용서되지 않습니다. ) 배열 변수의 이름에는 반드시 브랙킷 ([])이 붙으므로, 변수의 형태는 문맥에 대해 뚜렷합니다.

특수한 변수로서 scale, ibase, obase, last 의 4 개의 변수가 있습니다. scale 로 계산시의 소수점 이하의 유효 자리수를 지정합니다. scale 의 디폴트는 0 입니다. ibase 와 obase 로 입력 및 출력의 변환 기수를 지정합니다. 디폴트에서는, 입력, 출력의 기수는 모두 10 입니다. last 는, 마지막에 bc 가 출력한 수를 보관 유지하고 있습니다 (이것은 확장 기능입니다). 이것들에 대해서는, 다음에 적절한 곳에서 자세하게 설명합니다. 이러한 변수에는, 식에서 사용되는 대입과 같은 대입을 실시하는 것이 가능합니다.

  코멘트
bc 는, /* 로부터 */ 의 사이를 코멘트로서 취급합니다. 코멘트는 어디에서 시작되어 있어도 자주(잘), 1 캐릭터의 공백으로서 다루어집니다. (이것에 의해, 코멘트는 그 전후의 입력 아이템을 떼어냅니다. 예를 들어, 변수명의 도중에 코멘트를 둘 수 없습니다. ) 코멘트안에는 몇 개 개행이 있어도 괜찮습니다.

bc 를 스크립트로서도 사용할 수 있도록(듯이) 하기 위한(해), 1 행 코멘트가 확장 기능으로서 추가되었습니다. 1 행 코멘트는 # 로 시작되어, 다음의 개행까지 유효합니다. 그 개행 캐릭터 자체는 코멘트의 일부라고는 보이지 못하고, 보통으로 처리됩니다.

  식
`수'는, 식 및 문장에 의해 조작됩니다. 이 언어는 대화적으로 되도록(듯이) 설계되고 있기 (위해)때문에, 문장 및 식은 가능한 한 즉석에서 실행됩니다. "main" 프로그램이라고 한 것은 없고, 그 대신, 코드는 거기에 우연히 만난 시점에서 실행됩니다. (다음에 말하는`함수'는, 거기에 우연히 만난 시점에서 정의됩니다. )

식의 가장 단순한 것은, 단순한 정수입니다. bc 는, 입력되었다 정수를, 변수 ibase 로 지정되는 현재의 기수를 바탕으로, 내부적으로는 10 진표현의 수로 변환합니다. (함수의 경우에는 예외가 있습니다. ) ibase 에는, 2 에서 16 까지를 사용할 수 있습니다. 이 범위를 넘는 값을 ibase 에 대입하려고 하면(자), 2 혹은 16 을 지정한 것이 됩니다. 수의 입력에는,0-9 및 A-F 의 캐릭터를 이용할 수 있습니다. (주의: 이것은 대문자가 아니면 안됩니다. 소문자는 변수명입니다. ) 1 자리수의 수는 ibase 의 값에 관계없이 그 값을 가집니다 (즉 A=10). 복수자리수의 수의 경우, bc 는 ibase 이상의 값을 가지는 모든 입력자리수를 ibase-1으로 변경합니다. 이것에 의해, 수 FFF 는 항상, 그 입력 기수를 사용해 3 자리수로 표현 가능한 최대의 값을 나타냅니다.

모든 연산식이, 다른 많은 고급언어를 닮은 것이 되고 있습니다. 수의 형태는 1 종류 밖에 없기 때문에, 형태 변환의 규칙은 없습니다. 그 대신, 식의 유효 자리수에 관한 규칙이 있습니다. 모든 식에 유효 자리수가 있어, 이것은 그 피연산수의 유효 자리수와 베풀어지는 연산, 거기에 많은 경우, 변수 scale 로부터 결정됩니다. scale 에는, 0 으로부터 C 의 정수로 표현할 수 있는 최대의 값까지가 지정 가능합니다.

이하, bc 로 사용 가능한 연산자를 설명합니다. 덧붙여 완전형의 식을 "expr", 단순 변수 또는 배열 변수를 "var" 라고 표기합니다. 단순 변수는 단지
    name
(와)과 나타내, 배열 변수는
    name[expr]
(와)과 나타냅니다. 특히 언급하지 않는 한, 결과의 유효 자리수는, 주목하고 있는 식의 최대 유효 자리수가 됩니다.

- expr
    결과는 그 식의 부호를 반전한 것이 됩니다.

++ var
    변수를 1 만 인크리먼트(increment) 해, 그 새로운 값이 식의 결과가 됩니다.

-- var
    변수를 1 만 감소 해, 그 새로운 값이 식의 결과가 됩니다.

var ++
    식의 결과는 그 변수의 값이 되어, 그리고 그 변수를 1 만 인크리먼트(increment) 합니다.

var --
    식의 결과는 그 변수의 값이 되어, 그리고 그 변수를 1 만 감소 합니다.

expr + expr
    식의 결과는 2 개의 식의 화가 됩니다.

expr - expr
    식의 결과는 2 개의 식의 차이가 됩니다.

expr * expr
    식의 결과는 2 개의 식의 적이 됩니다.

expr / expr
    식의 결과는 2 개의 식의 상이 됩니다. 결과의 scale 는 변수 scale 의 값이 됩니다.

expr % expr
    결과는, 이하와 같이 해 구할 수 있는 잉여입니다. a%b 를 요구하기 위해서(때문에), 우선 a/b 를 scale 의 유효 자리수로 계산합니다. 이 결과를 이용해, a-(a/b) *b 를, scale+scale(b)와 scale(a)의 큰 (분)편의 유효 자리수로 계산합니다. 만약 scale 에 0 이 세트 되어 양쪽 모두의 식이 정수이면, 정수의 잉여가 요구됩니다.

expr ^ expr
    식의 결과는, 1 번째의 식의 값을 2 번째의 회수만 곱한 것이 됩니다. 2 번째의 식은, 정수가 아니면 안됩니다. (2 번째의 식이 정수가 아닌 경우는 경고가 표시되어 정수에 절약한 값이 사용됩니다. ) 결과의 scale 는, 나무 지수가 부라면 scale 가 됩니다. 나무 지수가 정이라면, "1 번째의 식의 scale 날 수 있는 나무 지수와의 적" 및 "scale 와 1 번째의 식의 scale 의 큰 (분)편" 중 작은 (분)편 (즉, scale(a^b) = min(scale(a) *b, max( scale, scale(a)))) 됩니다. expr^0 는 항상 1 을 돌려줍니다.

( expr )
    표준의 우선도를 사용하지 않고 , 이 식의 평가를 우선합니다.

var = expr
    식의 값이 변수에 대입됩니다.

var <op>= expr
    "var" 가 한 번 밖에 평가되지 않는 것 이외는 "var = var <op> expr" 와 같습니다. "var" 가 배열의 경우는 동작이 다른 일이 있습니다.

관계 연산은 특수한 연산으로, 결과는 항상 0 이나 1 이 됩니다. 관계가 가짜때 0, 진정한 때 1 이 됩니다. 관계 연산은, 연산식의 어디에서라도 사용할 수가 있습니다. (POSIX bc에서는, 관계 연산은, if, while, for 문안만으로, 게다가 1 개의 관계식 밖에 사용할 수 없습니다. ) 관계 연산자는 이하와 같다.

expr1 < expr2
    expr1 가 expr2 보다 작은 경우 1 이 됩니다.

expr1 <= expr2
    expr1 가 expr2 보다 작은가 동일한 경우 1 이 됩니다.

expr1 > expr2
    expr1 가 expr2 보다 큰 경우 1 이 됩니다.

expr1 >= expr2
    expr1 가 expr2 보다 큰가 동일한 경우 1 이 됩니다.

expr1 == expr2
    expr1 와 expr2 가 동일한 경우 1 이 됩니다.

expr1 ! = expr2
    expr1 와 expr2 가 동일하지 않은 경우 1 이 됩니다.

논리 연산도 사용할 수 있습니다. (POSIX bc 에는 논리 연산은 없습니다. ) 논리 연산도 관계 연산과 같이, 결과는 0 이나 1 (각각가짜 및 진)이 됩니다. 논리 연산자는 이하와 같다.

! expr
    expr 가 0 이라면 1 이 됩니다.

expr && expr
    expr1 와 expr2 가 양쪽 모두 0 이 아니면, 1 이 됩니다.

expr || expr
    expr1 와 expr2 의 어느 쪽인지 한편이 0 이 아니면, 1 이 됩니다.

각 연산자의 우선 순위와 결합 규칙은 다음과 같습니다. (최초의 것만큼 낮고, 후에 갈 만큼 높은 우선 순위로 먼저 실행됩니다. )
    ||               (왼쪽으로부터 결합)
    &&               (왼쪽으로부터 결합)
    !                 (결합하지 않고)
    관계 연산         (왼쪽으로부터 결합)
    대입 연산         ( 오른쪽으로부터 결합)
    +  -             (왼쪽으로부터 결합)
    * / %            (왼쪽으로부터 결합)
    ^                ( 오른쪽으로부터 결합)
    - (단항 마이너스) (결합하지 않고)
    ++ --            (결합하지 않고)

이 우선 순위는, POSIX bc 의 프로그램이 그대로 올바르게 움직이도록(듯이) 배려하고 결정되어 있습니다. 이 때문에, 관계 연산과 논리 연산을 대입문과 함께 이용했을 경우, 통상과는 다른 행동을 합니다. 다음의 예를 생각해 봅시다:
    a = 3 < 5

C 프로그래머의 대부분은, ``3 < 5''의 관계 연산이 실행된 결과 (즉 1)가 변수 ``a''에 대입되는, (이)라고 생각하겠지요. 그런데 bc 에서는, 우선 3 이 변수 ``a''에 대입되어 그리고 3 으로 5 의 비교를 합니다. 이전 차이를 피하기 위해서(때문에), 관계 연산이나 논리 연산을 대입 연산과 함께 이용하는 경우는, 괄호를 사용하는 것이 최선입니다.

bc 에는 특별한 식이 한층 더 몇개인가 갖춰지고 있습니다. 그것은 유저 정의 함수와 표준 함수에 관한 것으로, 모두 "name(parameters) " 라고 하는 형태를 하고 있습니다. 유저 정의 함수에 대해서는 함수의 장을 참조해 주세요. 표준 함수는 이하와 같습니다:

length ( expression )
    expression 의 유효 자리수를 돌려줍니다.

read ( )
    (확장 기능) 함수의 출현 위치에 관계없이, 표준 입력으로부터 수를 읽어냅니다. 데이터와 프로그램의 양쪽 모두를 표준 입력으로부터 주는 것 같은 경우에는, 문제를 생길 수 있는 것에 주의해 주세요. 최선의 방법은, 유저로부터 데이터의 입력의 필요가 있다면, 프로그램은 미리 만들어 두어, 표준 입력으로부터 프로그램을 입력하지 않게 하는 것입니다. read 함수의 값은 표준 입력으로부터 읽어들인 수입니다. 그 때, 변환 기수로서 변수 ibase 의 현재의 값이 이용됩니다.

scale ( expression )
    expression 의 소수점 이하의 유효 자리수를 돌려줍니다.

sqrt ( expression )
    expression 의 평방근을 돌려줍니다. expression 에 부의 값을 지정했을 경우는, 런타임 에러가 됩니다.

  문
문장은 (대부분의 산술 언어가 그렇듯이), 처리를 차례로 실행해 나가는 단위입니다. bc 에서는 문장은 「가능한 한 빠른 단계에서」실행됩니다. 개행이 입력된 시점에서, 실행 가능한 문장이 존재하고 있으면, 즉석에서 실행합니다. 이 때문에 bc 에서는 개행이 중요한 역할을 가지고 있습니다. 실제, 세미콜론과 개행이 문장의 단락으로서 사용됩니다. 부적당한 장소에서 개행을 입력하면(자), 문법 에러가 됩니다. 개행은 문장의 단락입니다만, backslash를 이용해 개행을 숨길 수가 있습니다. bc 에 있어,"\<nl>" (<nl>는 개행)는 개행은 아니고 공백으로 보입니다. 문장의 리스트는, 세미콜론과 개행으로 단락지어진 문장의 줄입니다. 이하, bc 의 문장의 종류와 그 동작에 대해 설명합니다. (덧붙여 이하의 설명으로 ([])로 괄부분은 생략 가능한 항입니다. )

연산식 연산식에는 다음의 2 개의 종류가 있습니다. 연산식이 "<variable> <assignment> ..." 그리고 시작되어 있으면, 그것은 대입문으로서 다루어집니다. 그렇지 않으면, 연산식은 평가되어 출력에 표시됩니다. 결과가 표시된 후, 개행이 표시됩니다. 예를 들면,"a=1" 는 대입문이며, "(a=1)" (은)는 대입문이 파묻힌 연산식입니다. 표시되는 수치는 모두, 변수 obase 로 정해지는 기수로 표시됩니다. obase 로 지정할 수 있는 값은 2 로부터 BC_BASE_MAX 까지입니다. ( 「제한」의 장을 참조. ) 기수 2 에서 16 까지에서는, 통상의 수의 표 기법이 이용됩니다. 기수가 16 보다 큰 경우, bc 는, 각 형을 10 진표기하는 복수자리수 캐릭터 표기법으로 표시합니다. 복수자리수 캐릭터 표기법에서는, 각 형은 공백에서 단락지어집니다. 각 형은 "obase-1" 를 10 진으로 표기하는데 필요한 자리수의 숫자로부터 완성됩니다. 수의 정밀도는 임의에 선택할 수 있기 (위해)때문에, 수에 따라서는 1 행에 표시할 수 없는 경우도 있습니다. 그러한 긴 수는, 줄 끝에 "\" 를 붙여 다음 행에 계속합니다. 1 행에 표시할 수 있는 캐릭터수는 70 입니다. bc 의 대화적 성질에 의해, 어느 수를 표시하면(자), 표시한 값이 특수 변수 last 에 대입된다고 하는 부작용이 생깁니다. 유저는 다시 타이프 치는 일 없이 마지막에 표시된 값을 재이용할 수 있습니다. last 에 값을 대입하는 일도 가능해, 그 경우, 전회 표시된 값이 대입치로 덧쓰기됩니다. 새롭게 대입한 값은, 다음에 수가 표시될까 다른 값이 last 에 대입된다 까지 유효합니다. (bc 의 실장에 따라서는, 수의 일부로 되어 있지 않은 단일의 피리어드 (. )(을)를 last 의 단축 표기로서 이용할 수가 있습니다. )

string
    캐릭터 라인 string 가 출력에 표시됩니다. 캐릭터 라인은 이중 인용부호로 시작되어, 다음의 이중 인용부호까지의 모든 캐릭터를 포함합니다. 개행을 포함해 모든 캐릭터는 문자 그대로에 해석됩니다. 캐릭터 라인의 뒤에 개행은 출력되지 않습니다.

print list
    print 문 (이것은 확장 기능입니다)은, 또 하나의 출력 방법입니다. "list" 는 콤마로 단락지은 캐릭터 라인 및 연산식의 리스트이며, 각 캐릭터 라인 혹은 연산식이 리스트의 순서에 표시됩니다. 마지막에 개행은 출력되지 않습니다. 연산식은 평가되어 그 값이 표시되는 것과 동시에, 변수 last 에 대입됩니다. print 문중의 캐릭터 라인은 출력에 표시됩니다만, 특수 캐릭터를 포함할 수가 있습니다. 특수 캐릭터는 backslash (\)로 시작됩니다. bc 로 사용할 수 있는 특수 캐릭터는, "a" (벨),"b" (백 스페이스), "f" (form feed),"n" (개행),"r" (복귀),"q" (이중 인용부호), "t" (탭),"\" (backslash)입니다. 이외는 무시됩니다.

{ statement_list }
    복문입니다. 복수의 문장을 1 개의 그룹에 정리해 실행합니다.

if ( expression ) statement1 [else statement2]
    if 문은 연산식 expression 를 평가해, 그 값에 응해 문장 statement1 또는 문장 statement2 를 실행합니다. expression 의 값이 0 이 아니면 statement1 가 실행됩니다. statement2 가 존재해, expression 의 값이 0 이라면, statement2 가 실행됩니다. (else 절은 확장 기능입니다. )

while ( expression ) statement
    while 문은 expression 가 0 이 아닌 동안, 반복 statement 를 실행합니다. statement 의 실행전에 매회 expression 를 평가합니다. expression 의 값이 0 이 되는지, break 문을 실행하면(자), 루프가 종료합니다.

for ( [expression1] ; [expression2] ; [expression3] ) statement
    for 문은 statement 의 반복 실행을 제어합니다. expression1 는 루프 실행 전에 평가됩니다. expression2 는 statement 의 실행전에 매회 평가되어 그 값이 0 이 아니면 statement 가 실행됩니다. expression2 의 값이 0 이 되면(자), 루프는 종료합니다. 각 statement 실행의 뒤, 다시 expression2 가 평가되기 전에 expression3 가 평가됩니다. expression1 혹은 expression3 가 생략 되고 있으면(자), 그곳에서는 아무것도 평가되지 않습니다. expression2 가 생략 되고 있는 경우, expression2 가 1 인 것과 (와)과 같이 다루어집니다. ( 각 expression 가 생략 가능한 것은 확장 기능입니다. POSIX bc 에서는, 3 개의 expression 는 어느 것도 생략 할 수 없습니다. ) 이하는 for 문과 등가인 코드입니다:
    expression1;
    while (expression2) {
       statement;
       expression3;
    }

break
    그것을 포함한 가장 안쪽의 while 혹은 for 문에 의한 반복을 강제적으로 중단합니다.

continue
    그것을 포함한 가장 안쪽의 for 문에 있어서의 다음의 반복하러 진행됩니다. (continue 문은 확장 기능입니다)

halt
    실행되면(자) bc 프로세서를 종료시킵니다(확장 기능). 예를 들면 "if (0 == 1) halt" 의 경우는 bc 는 종료하지 않습니다. halt 문이 실행되지 않기 때문입니다.

return
    함수로부터 돌아옵니다. 함수의 결과는 0 이 됩니다. (함수의 장을 참조)

return ( expression )
    함수로부터 돌아옵니다. 함수의 결과는 expression 가 됩니다. (함수의 장을 참조) 확장 기능입니다만, 괄호는 필수가 아닙니다.

  유사문
이것들은 지금까지의 문장과는 동작이 다릅니다. 유사문은 실행문이 아니고, 「컴파일」 시점에서 처리됩니다.

limits
    bc 의 로컬 버젼에 의해 제한되는 한계치를 표시합니다. (limits 는 확장 기능입니다)

quit
    bc 를 종료합니다. 어떤 장소에 있어도, quit 문은 입력된 시점에서 실행됩니다. 예를 들면, "if (0 == 1) quit" 그렇다고 하는 기술이어도, bc 는 종료합니다.

warranty
    프로텍션에 관한 주의를 길쭉하게 표시합니다. (warranty 는 확장 기능입니다)

  함수
함수는, 다음에 실행되어야 할 계산 순서를 정의하는 기능입니다. bc 의 함수는 항상 값을 계산해, 그것을 불러내 측에 돌려줍니다. 함수 정의는, 그것이 입력으로부터 읽힌 시점에서 정의를 한다고 하는 점으로 「다이나믹(동적)」입니다. 한 번 정의된 함수는, 같은 이름으로 다른 함수가 정의될 때까지 사용 가능해, 새로운 함수가 정의되었을 경우는, 전의 함수를 옮겨놓을 수 있습니다. 함수의 정의는, 이하와 같이 실시합니다:
    define name ( parameters ) { newline
        auto_list   statement_list }
함수 호출은, "name(parameters) " 그렇다고 하는 형식의 연산식입니다.

파라미터 parameters 는 수많은 있고는 배열 (확장 기능)입니다. 함수 정의에서는, 0 혹은 1 개 이상의 파라미터명을 콤마로 단락지어 늘어놓는 것으로 정의합니다. 수는 값인도(call by value)에서만 건네받아 배열은 변수 인도(call by variable)로 마셔 건네받습니다. 배열은 파라미터 정의중에서 "name[]" 와 같이 표기해 지정합니다. 함수 호출에서는, 수의 파라미터에 대해서 완전한 연산식의 열매 파라미터를 기술합니다. 배열을 건네주는 표기는 배열 파라미터 정의와 같습니다. 이름 첨부 배열은 변수(variable)에 의해 함수에게 건네집니다. 함수 정의는 다이나믹 이유, 파라미터의 수와 형태는 함수 호출 시에 체크됩니다. 파라미터의 수많은 있고는 형태에 어떠한 부정합이 있으면(자), 런타임 에러가 발생합니다. 미정도리 함수를 호출했을 경우도 런타임 에러가 됩니다.

auto_list 는 생략 가능해, 로컬 변수로서 사용하는 변수의 리스트 입니다. auto_list 가 존재한다면, 그 문법은 "auto name, ... ;" 됩니다. (세미콜론은 생략 가능합니다. ) 각 name 가 로컬 변수의 이름이 됩니다. 배열은 파라미터와 같은 표기로 지정할 수 있습니다. 이러한 변수는, 함수의 최초로 그 값이 스택에 푸쉬 된 후 값 0 에 초기화되어 함수의 실행중에 사용됩니다. 이러한 변수는 함수 출구에서 팝 되어 (함수 호출시의) 원의 값이 복원됩니다. 파라미터는 실제로는 로컬 변수이며, 함수 호출로 주어진 값에 초기화됩니다. bc 의 로컬 변수는 전통적인 의미에서의 로컬 변수와 달리, 함수 A 가 함수 B 를 호출하고 있는 것 같은 경우, 함수 B 안에 함수 A 의 로컬 변수와 같은 이름의 로컬 변수가 없는 한, 함수 A 의 로컬 변수명을 그대로 사용해, 함수 B 로부터 함수 A 의 로컬 변수를 액세스 할 수 있습니다. 로컬 변수와 파라미터는 스택에 푸쉬 되기 (위해)때문에, bc 는 재귀적인 함수 호출을 서포트하고 있습니다.

함수 본체는 bc 의 문장의 리스트입니다. 되풀이하여 말하면, 문장은 세미콜론이나 개행으로 단락지어지고 있습니다. return 문에 의해 함수는 종료해, 값을 돌려줍니다. return 문에는 2 개의 형식이 있어, 첫번째 형식 "return" 는, 호출 바탕으로치 0 을 돌려줍니다. 또 하나의 형식 "return ( expression ) " 는, expression 의 값을 계산해, 그것을 호출해 바탕으로 돌려줍니다. 각 함수의 마지막에는 "return (0) " 가 있는 것이라고 해석됩니다. 이것에 의해, 명시적으로 return 문을 두지 않아도, 함수는 종료해 값 0 을 돌려줍니다.

함수 중(안)에서는, 변수 ibase 의 동작이 바뀝니다. 함수 중(안)에서 사용되어 있는 정수는, 함수의 호출 시점의 ibase 를 바탕으로 변환을 합니다. 이 때문에, 함수 내부에서 ibase 를 변경해도 무시됩니다. 다만, 안표 준함수 read 를 호출했을 경우는 예외로, 이것은 항상 현재의 ibase 의 값을 기초로 변환을 합니다.

확장 기능입니다만, 정의의 서식이 약간 완만하게 되었습니다. 표준에서는, 여는 brace가 define 키워드와 같은 행에 있는 것으로, 다른 부분이 계속하는 행에 있는 것이 필수입니다. 본버젼의 bc 에서는, 함수가 여는 brace의 전후의 개행수는 임의입니다. 예를 들면, 다음의 정의는 합법입니다.

    define d (n) { return (2*n); }
    define d (n)
      { return (2*n); }

  수학 프로그램 라이브러리
bc 에 -l 옵션을 붙여 기동했을 경우는, 수학 프로그램 라이브러리가 읽혀 디폴트의 scale 가 20 으로 설정됩니다. 수학 함수는, 그것을 호출한 시점의 scale 의 값에 따라 계산을 실시합니다. 수학 프로그램 라이브러리에 의해 사용 가능하게 되는 함수는, 다음과 같습니다:

s (x)
    sin (x 의 단위는 라디안)

c (x)
    cos (x 의 단위는 라디안)

a (x)
    atan (돌아가 값의 단위는 라디안)

l (x)
    log (자연대수)

e (x)
    exp (지수함수)

j (n, x)
    정수 n 다음의 벳셀 함수

  사용예
다음의 예는, /bin/sh 로 셸 변수 pi 에 ``파이''의 값을 대입합니다.
    pi=$(echo "scale=10; 4*a(1)" | bc -l)

다음의 예는, 수학 프로그램 라이브러리로 사용되고 있는 ``e (x)''의 정의입니다. 이 함수는 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
      }
    }

다음의 예는, bc 의 확장 기능을 사용해, ``checkbook balances'' (수표장잔고)(을)를 계산하는 간단한 프로그램입니다. 이 프로그램을 파일로 해 두면(자), 매회 타이프 치고 더 좌도에 몇번이나 사용할 수가 있습니다.

    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

다음의 예는, 재귀 호출에 의해 계승을 계산하는 함수입니다.

    define f (x) {
      if (x <= 1) return (1);
      return (f(x-1) * x);
    }

  readline 와 libedit 의 옵션
GNU bc 는 (configure 의 옵션에 의해) GNU readline 입력 에디터 프로그램 라이브러리 또는 BSD libedit 프로그램 라이브러리 (을)를 사용하도록(듯이) 컴파일 할 수 있습니다. 이것은, bc 에 입력하기 전에, 행의 편집을 가능하게 합니다. 이전에 입력한 행의 역사도 이용 가능하게 됩니다. 이 옵션으로 컴파일 된 bc 에서는, 게다가 1 개(살)의 특수한 변수 history 가 추가되어 역사에 보존되는 행의 수를 지정합니다. readline 에서는, 그 값이 -1 (기본값)라면, 역사행은 제한없이 보존됩니다. 정의 수를 지정하면(자), 역사행이 그 수에 제한됩니다. 0 이라면 역사 기능이 무효가 됩니다. 기본값은 100 입니다. 자세하게는, 유저 메뉴얼의 GNU readline 와 history 프로그램 라이브러리와 BSD libedit 를 봐 주세요. readline 와 libedit 의 양쪽 모두를 동시에 유효화할 수 없습니다.

  차이점
이 버젼의 bc (은)는 POSIX P1003. 2/D11 드래프트로부터 실장되고 있어 그 드래프트나 이전의 실장에 비해 몇개의 차이점이나 확장점이 있습니다. 전통적으로 행해지고 있던 것 같은 dc(1) (을)를 이용한 실장이 아닙니다. 이 버젼은 단일 프로세스이며, 프로그램을 바이트 코드로 변환한 것을 해석해 실행합니다. 「문서에 기재되지 않았다」옵션 (-c)이 있어, 프로그램을 실행하는 대신에, 그것을 바이트 코드로 변환한 결과를 표준 출력에 출력합니다. 이것은 주로, 파서의 디버그와 수학 프로그램 라이브러리의 준비에 이용되었습니다.

주된 차이점은 확장 기능에 의하는 것입니다. 기능을 높이거나 추가하거나 하기 위해서 기능이 확장되거나 신기능이 추가 되거나 하고 있습니다. 차이점과 확장점의 리스트를 이하에 나타냅니다.

LANG 환경 변수
    이 버젼은, 환경 변수 LANG 및 LC_ 로 시작되는 모든 환경 변수의 처리에 관해서 POSIX 표준에 준거하고 있지 않습니다.

이름  전통적인 bc 및 POSIX bc (은)는, 함수, 변수, 배열의 이름으로서 단일의 캐릭터를 사용합니다. 이 버젼에서는, 선두가 캐릭터로 시작되어, 캐릭터와 숫자와 언더 스코아로 구성되는 2 캐릭터 이상의 이름을 사용할 수 있도록(듯이) 확장되고 있습니다.

캐릭터 캐릭터 라인에는 NUL 캐릭터를 포함할 수 없습니다. POSIX 에서는, 캐릭터 라인에는 모든 캐릭터를 포함할 수가 없으면 안 되는, (으)로 하고 있습니다.

last
    POSIX bc 에는 변수 last 는 없습니다. bc 의 실장에 따라서는, last 와 같은 의미로 피리어드 (. )(을)를 이용하는 것이 있습니다.

비교  POSIX bc 에서는, 비교는 if 문, while 문, for 문의 제 2 식 중(안)에서 마셔 이용할 수가 있습니다. 또, 이러한 문장 중(안)에서는 다만 1 개의 관계 연산 밖에 사용할 수 없습니다.

if 문, else 절
    POSIX bc 에는 else 절은 없습니다.

for 문
    POSIX bc 에서는 for 문의 각 연산식은 생략 할 수 없습니다.

&&, ||, !
    POSIX bc 에는 논리 연산자는 없습니다.

read 함수
    POSIX bc 에는 read 함수는 없습니다.

print 문
    POSIX bc 에는 print 문은 없습니다.

continue 문
    POSIX bc 에는 continue 문은 없습니다.

return 문
    POSIX bc 에서는, return 문의 주위에 괄호가 필요합니다.

배열 파라미터
    POSIX bc 에서는 (현재로서는) 배열 파라미터는 완전하게는 사용할 수 없습니다. POSIX 의 문법에서는, 함수 정의에서는 배열을 사용할 수 있습니다만, 실제로 호출할 때의 파라미터에 배열을 지정할 수가 없습니다. (이것은 아마, 문법상의 간과지요. ) 전통적인 bc 의 실장에서는, 배열 파라미터는 값인도 만이었습니다.

function format
    POSIX bc 에서는, 여는 brace가 define 키워드와 같은 행에 있어, auto 문이 다음의 행에 있는 것이 필요합니다.

=+, =-, =*, =/, =%, =^
    POSIX bc 에서는 이러한 「구식」의 대입 연산자를 정의할 필요는 없습니다. 이 버젼에서는 이러한 「구식」대입 연산자를 사용할 수 있을지도 모릅니다. limits 문을 사용해, 인스톨 한 버젼이 이것들을 서포트하고 있을까 부디 확인해 봐 주세요. 만약 그 버젼이 「구식」대입 연산자를 서포트하고 있으면, 문장 "a =- 1" 은 a 에 값 -1 을 대입하는 대신에 a 를 1 줄입니다.

숫자 표기중의 공백
    다른 bc 실장에서는, 숫자 표기안에 공백을 포함하는 것이 허락됩니다. 예를 들면,"x=1 3" 은 변수 x 에 값 13 을 대입합니다. 이 버젼의 bc 에서는, 앞의 문장은 문법 에러가 됩니다.

에러와 실행
    이 버젼의 bc 는, 프로그램에 문법상의 에러나 다른 에러가 발견되었을 경우에 어떤 코드가 실행되는지, 그렇다고 하는 점으로, 다른 실장과 다르고 있습니다. 어느 함수 정의중에서 문법 에러가 발견되면(자), 에러 회복 기구는 문장의 선두를 찾아내 함수의 파스를 계속하려고 노력하겠습니다. 한번 함수 중(안)에서 문법 에러가 발견되면(자), 그 함수는 호출할 수 없게 되어, 미정도리 상태가 됩니다. 대화적 실행 코드로 문법 에러가 있으면(자), 현재의 실행 블록이 무효가 됩니다. 실행 블록과는, 사람 계속의 완전한 문장의 뒤의 줄 끝까지입니다. 예를 들면, 다음의 코드
    a = 1
    b = 2
에는 2 개의 실행 블록이 있어,
    { a = 1
      b = 2 }
에는 1 개의 실행 블록이 있습니다. 런타임 에러가 발생하면(자), 현재의 실행 블록의 실행이 종료합니다. 런타임의 경고가 발생해도, 현재의 실행 블록은 종료하지 않습니다.

세치기 대화 세션의 사이, SIGINT 시그널 (통상, 단말로부터의 Control-C 입력으로 발생합니다)에 의해 현재의 실행 블록의 실행이 중단되어 어느 함수가 중단되었는지를 나타내는 「런타임」에러가 표시됩니다. 런타임의 데이터 구조를 모두 클리어 한 후 메세지가 표시되어 bc 는 다음의 입력을 받아들이는 상태가 된 것을 나타냅니다. 지금까지 정의한 함수는 모두 정의되어 남아 있어 로컬이 아닌 변수의 값은 하락해 발생시점의 값대로 되어 있습니다. 로컬 변수와 함수 파라미터는 모두, 클리어 처리에 의해 소거됩니다. 비대화 세션에서는, SIGINT 시그널로 bc 의 실행 전체가 종료합니다.

  한계
이하의 항목이 현재의 bc 프로세서의 한계치가 되고 있습니다. 이 중 몇개인가는, 인스톨시로 변경할 수 있습니다. 실제의 값을 얻으려면 limits 문을 사용해 주세요.

BC_BASE_MAX
    현재로서는, 출력의 기수의 최대치는 999 로 설정되어 있습니다. 입력측의 기수의 최대치는 16 입니다.

BC_DIM_MAX
    현재로서는 65535 로서 배포되고 있습니다만, 인스톨 한 버젼에서는 차이가 날지도 모릅니다.

BC_SCALE_MAX
    소수점 이하의 자리수는 INT_MAX 자리수에 제한되고 있습니다. 또, 소수점보다 위의 자리수도 INT_MAX 자리수에 제한되고 있습니다.

BC_STRING_MAX
    캐릭터 라인중의 캐릭터수는 INT_MAX 캐릭터에 제한되고 있습니다.

지수  누승 연산 (^)의 지수의 값은 LONG_MAX 에 제한되고 있습니다.

변수명 단순 변수, 배열, 함수 각각에 대해, 일의에 식별되는 이름은 32767 개에 제한되고 있습니다.

환경 변수
bc 는 이하의 환경 변수를 해석합니다.

POSIXLY_CORRECT
    -s 옵션과 같습니다.

BC_ENV_ARGS
    이것은 bc 에 인수를 건네주는 다른 방법으로, 명령행 당겨 수와 같은 서식입니다. 이 인수가 최초로 처리되므로, 이 환경 변수로 지정된 파일은 명령행 인수로 지정된 파일보다 먼저 처리됩니다. 이것에 의해, 매회 bc 를 호출할 때 마다 처리하는 「표준의」옵션이나 파일을 설정할 수 있습니다. 이 환경 변수로 지정하는 파일에는, bc 를 달리게 할 때마다 정의해 두고 싶은 것 같은 함수의 정의를 써 두면(자) 좋을 것입니다.

BC_LINE_LENGTH
    숫자를 출력할 때의 1 행의 캐릭터수를 정수로 지정합니다. 숫자가 너무 길면(자), backslash와 개행을 포함한 출력이 됩니다.

진단
명령행으로 지정한 파일을 오픈할 수 없는 경우, bc 는 파일을 이용할 수 없는 취지를 표시해 종료합니다. 또, 컴파일시 혹은 런타임의 진단 메세지도 있습니다만, 그것들은 자신으로 이해할 수 있게 되어 있을 것입니다.

버그
에러 리커버리가 아직 잘되고 있지 않습니다.

버그 보고는, bug-bc@gnu.org 에 전자 메일로 부탁합니다. 단어 ``bc''를 ``Subject:''필드의 어디엔가 넣어 두어 주세요.

저자
Philip A.  Nelson
philnelson@acm.org

사례
실장을 테스트할 때에 광범위하게 도와 준 Steve Sommars (Steve.Sommars@att.com)에 감사합니다. 많은 훌륭한 의견을 받았습니다. 그 덕분에 매우 좋은 것이 되었습니다.