나는 종종 bc
유틸리티를 사용하여 16진수를 10진수로 또는 그 반대로 변환합니다. 그러나 구성 방법 ibase
과 obase
구성 방법은 항상 시행착오의 문제입니다. 예를 들어 여기서는 16진수 값 C0을 10진수로 변환하고 싶습니다.
$ echo "ibase=F;obase=A;C0" | bc
180
$ echo "ibase=F;obase=10;C0" | bc
C0
$ echo "ibase=16;obase=A;C0" | bc
192
여기서 논리는 무엇입니까? obase
(세 번째 예에서) A
변환되는 값(세 번째 예에서)과 동일한 진수여야 하며(세 번째 예에서) 변환하려는 진수에 있어야 합니까?C0
ibase
16
답변1
당신이 정말로 하고 싶은 말은 다음과 같습니다.
$ echo "ibase=16; C0" | bc
192
16진수에서 10진수로의 경우 다음과 같습니다.
$ echo "obase=16; 192" | bc
C0
10진수에서 16진수로의 경우.
ibase
십진수와 관련된 변환의 경우 이 설정의 기본값은 10이므로 및 를 모두 제공할 필요가 없습니다 .obase
너하다이진수에서 16진수 등으로 변환하려면 둘 다 제공되어야 합니다. 이 경우 먼저 다음을 제공하면 상황을 이해하는 것이 가장 쉽다는 것을 알았습니다 obase
.
$ echo "obase=16; ibase=2; 11000000" | bc
C0
먼저 제공하면 ibase
다음 설정의 해석이 변경되므로 obase
명령은 다음과 같아야 합니다.
$ echo "ibase=2; obase=10000; 11000000" | bc
C0
이 순서에서는 obase
값이 2진수로 해석되므로 16진수 출력을 얻으려면 100002=16을 주어야 하기 때문입니다. 이것은 너무 서투른 일이다.
이제 세 가지 예가 이렇게 작동하는 이유를 알아 보겠습니다.
echo "ibase=F;obase=A;C0" | bc
180
이는 한 자리 값이 16진수로 해석되므로 입력 기수를 15로, 출력 기수를 10으로 설정하므로,POSIX에 따르면. 이는
bc
기본 A₁₅=10에 있는 C0₁₅이 무엇인지 알려달라고 요청하고 180₁₀라고 정확하게 대답합니다. 하지만 이는 확실히 여러분이 묻고 싶었던 질문은 아닙니다.echo "ibase=F;obase=10;C0" | bc
C0
이것은 기본 15 널 변환입니다.
왜? 첫째,
F
이전 예에서 지적한 것처럼 단일 숫자는 16진수로 해석되기 때문입니다. 그러나 이제 기본 15로 설정했으므로 다음 출력 기본 설정은 10₁₅=15로 해석되므로 C0₁₅에서 C0₁₅로 null 변환이 발생합니다.맞습니다. 출력은 가정한 대로 16진수가 아니라 15진법입니다!
F0
대신 전환을 시도하여 이를 스스로 증명할 수 있습니다C0
.F
15진수에는 숫자가 없으므로 고정bc
되어E0
출력으로 제공됩니다.E0
echo "ibase=16; obase=A; C0"
192
이것은 실제적으로 사용될 수 있는 세 가지 예 중 유일한 것입니다.
입력 기준을 16진수로 변경합니다.첫 번째
A
, 따라서 POSIX 사양 이 16진수(이 경우 10)로 해석되는 이유를 이해하기 위해 더 이상 POSIX 사양을 조사할 필요가 없습니다 . 유일한 문제는 출력 기준을 A₁₆=10으로 설정하는 것이 기본값이므로 중복된다는 것입니다.
답변2
설정한다는 것은 동일한 기준으로 설정 ibase
해야 함을 의미합니다 . obase
귀하의 예가 다음을 보여줄 것이라고 설명하십시오.
echo "ibase=F;obase=A;C0" | bc
bc
"ibase=F"를 사용하여 입력 숫자를 기본 15 숫자로 처리할 수 있습니다 . "obase=A"는 출력 숫자를 기본값인 10진수로 설정합니다.
bc
C0을 15진수로 읽습니다: C = 12. 12*15 = 180.
echo "ibase=F;obase=10;C0" | bc
이 예에서는 입력을 15진수로, 출력을 10으로 설정했습니다. 즉, 15진수에서 출력은 15진수입니다. 15진수의 C0 입력은 15진수의 C0 출력입니다.
echo "ibase=16;obase=A;C0" | bc
입력을 16진수로 설정하고 출력을 10진수로 설정합니다(16진수의 A는 10진수의 10과 같습니다).
C0은 10진법으로 변환됩니다: 12*16 = 192
내 개인적인 규칙은 먼저 obase를 설정하여 10진수를 사용할 수 있도록 하는 것입니다. 그런 다음 베이스 10을 사용하여 ibase를 설정합니다.
실제로 bc
한 가지 아이러니한 예외가 있습니다. ibase=A
즉, obase=A
입력과 출력은 항상 10진수로 설정됩니다. bc
매뉴얼 페이지 에서 :
Single digit numbers always have the value of the digit
regardless of the value of ibase.
이 동작은 다음 사양에 포함됩니다 bc
.2004 오픈그룹 bc
사양:
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.) Otherwise, the behavior is undefined
when digits greater than or equal to the value of ibase appear in
the input.
이것이 ibase=F
설정이 입력 베이스를 15진수로 변경하는 이유이며, 베이스를 설정하기 위해 항상 10진수를 사용하도록 권장하는 이유입니다. 자신을 혼동하지 마십시오.
답변3
모든 숫자는 GNU bc에 의해 현재 입력 베이스로 해석되며, 이는 숫자가 나타나는 명령문에 유효합니다. 현재 입력 이외의 숫자를 사용하면 해당 숫자는 기수에서 사용 가능한 가장 높은 숫자(10진수 9)로 해석됩니다. 여러 자리 값 또는 한 자리 숫자( A
== 10진수)로 사용되는 경우 일반 값입니다.
~에서GNU BC 매뉴얼:
의 값에 관계없이 단일 숫자는 항상 해당 숫자의 값을 갖습니다.데이터 베이스. (예: A = 10.) 여러 자리 숫자의 경우
bc
모든 입력 숫자를 다음보다 크거나 같도록 변경합니다.데이터 베이스값데이터 베이스-1. 이렇게 하면 숫자가FFF
항상 입력 베이스에서 가장 큰 3자리 숫자가 됩니다.
그러나 POSIX 표준은 다른 컨텍스트가 아닌 ibase
할당에 대해서만 이 동작을 정의한다는 점에 유의해야 합니다.obase
~에서BC의 SUS 사양:
언제라도데이터 베이스또는비만할당되었다숫자16진수로 간주되어야 하는 bc의 어휘 규칙 목록 값입니다. (예를 들어,데이터 베이스=A는 현재 전류에 관계없이 밑수 10으로 설정됩니다.데이터 베이스값. ) 그렇지 않으면 숫자가 다음보다 크거나 같을 때 동작이 정의되지 않습니다.데이터 베이스입력에 나타납니다. 둘 다데이터 베이스그리고비만초기값은 10입니다.
누락된 핵심 요소는 F가 실제로 16이 아니라 실제로 15이므로 ibase=F를 설정하면 입력 기준을 15로 설정한다는 것입니다.
따라서 ibase를 알 수 없음에서 16진수로 이식 가능하게 설정하려면 두 가지 문을 사용해야 합니다 ibase=A; ibase=16
. 그러나 프로그램 시작 부분에서는 그것이 십진수임을 믿고 그냥 ibase=16
.
답변4
Title ## 즉, ibase가 설정되면 입력한 모든 숫자는 해당 베이스에 들어갑니다. 그렇다면 다음과 같이 하세요.
ibase=16
그러면 이 뒤에 입력하는 모든 숫자는 16진수 숫자로 처리됩니다. 이렇게 하면 예상치 못한 결과가 발생할 수 있습니다. 그런 다음 obase를 기본 10으로 설정하거나 ibase를 재설정하려고 하면 숫자로 10이 아닌 A를 사용해야 합니다.
obase=A
bc에서는 다음을 입력하여 ibase 및 obase 값을 설정하지 않고도 확인할 수 있습니다.
ibase
16
obase
10
oneliner 용어로(16진수 13을 10진수로 변환:
echo "ibase=16;13;ibase;obase" | bc -l
19
16
10