bcを使って変換するときに「ibase」と「obase」を理解していますか?

bcを使って変換するときに「ibase」と「obase」を理解していますか?

私はしばしばbcユーティリティを使用して16進数を10進数に変換するか、その逆に変換します。ただし、構成方法ibaseobase構成方法は常に試行錯誤の問題です。たとえば、ここでは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(3番目の例では)A変換される値(3番目の例では)と同じ進数でなければならず(3番目の例では)、変換したい真数にする必要がありますか?C0ibase16

答え1

あなたが本当にやりたい言葉は次のとおりです。

$ echo "ibase=16; C0" | bc
192

16進数から10進数の場合は、次のようになります。

$ echo "obase=16; 192" | bc
C0

10進数から16進数への場合。

ibase10進数に関連する変換の場合、この設定のデフォルト値は10です。obase

あなたする2進数から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を指定する必要があるためです。これはとても不器用です。


次に、3つの例がこのように機能する理由を見てみましょう。

  1. echo "ibase=F;obase=A;C0" | bc

    180

    これは、1桁の値が16進数として解釈されるため、入力基数を15に、出力基数を10に設定するため、POSIXによると。これは、bc基本A₁₅=10のC0₁₅が何であるかを知らせるように求め、180₁₀と正確に答えます。しかし、これは確かにあなたが尋ねたかった質問ではありません。

  2. echo "ibase=F;obase=10;C0" | bc

    C0

    これはデフォルトの15ヌル変換です。

    なぜ?まず、F前の例で指摘したように、単一の数字は16進数として解釈されるためです。ただし、これはデフォルト15に設定されているため、次の出力デフォルト設定は10₁₅=15と解釈されるため、C0₁₅からC0₁₅へのnull変換が発生します。

    そうですね。出力は仮定した通り、16進数ではなく15進法です!

    F0代わりに、切り替えを試して自分で証明できますC0F15進数には数字がないため、固定されてbc出力E0として提供されます。E0

  3. echo "ibase=16; obase=A; C0"

    192

    これは実際に使用できる3つの例のうちの唯一のものです。

    入力基準を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 進数に設定します。

bcC0を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を使用してbabesを設定します。

実際にはbc1つの皮肉な例外があります。ibase=Aつまり、obase=A入力と出力は常に10進数に設定されます。bcマニュアルページから:

Single digit numbers always have the value of the digit 
regardless of the value of ibase.

この動作は次の仕様に含まれていますbc2004年オープングループ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)として解釈されます。複数桁の値または1桁の数字(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に設定することです。

したがって、バネを不明から16進数に移植可能に設定するには、2つのステートメントを使用する必要がありますibase=A; ibase=16。しかし、プログラムの冒頭では、それが10進数であると信じているだけですibase=16

答え4

Title##つまり、baseが設定されている場合、入力したすべての数字はそのベースに入ります。その場合は、次のようにしてください。

ibase=16

これにより、この後に入力するすべての数字は16進数字として扱われます。これにより、予期しない結果が生じる可能性があります。その後、obaseをデフォルトの10に設定するか、abaseをリセットしようとすると、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

関連情報