bcを使用した変換の場合の「ibase」および「obase」を理解しますか?


22

bc16進数を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

ここのロジックは何ですか?obaseA私の3番目の例では)変換される値と同じベースにある必要があり(C0私の例では)、ibase163番目の例では)変換先のベースにある必要がありますか?


1
16進数の計算(16進数の入力と出力)では、ibaseの前にobaseを設定する必要があります!
パスカル

回答:


36

あなたが実際に言いたいことは:

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

16進数から10進数の場合:

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

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

これらの設定はデフォルトで10であるため、10進数を含む変換の場合、両方ibaseを指定する必要はありませんobase

あなたはない、そのようなバイナリ・ツー・六角などの変換のための両方を与える必要があります。その場合、obase最初に与えると物事を理解するのが最も簡単です:

$ echo "obase=16; ibase=2; 11000000" | bc
C0

あなたが与える場合はibase最初の代わりに、それは次の解釈変更するobaseコマンドがなければならないよう、設定を:

$ echo "ibase=2; obase=10000; 11000000" | bc
C0

これは、この順序ではobase値が2進数として解釈されるため、16進数で出力を取得するには10000₂= 16を指定する必要があるためです。それは不器用です。


次に、3つの例が同じように動作する理由を考えてみましょう。

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

    180

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

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

    C0

    これは、基数15のNULL変換です。

    どうして?まず、F前の例で指摘したように、1 桁が16進数で解釈されるためです。しかし、ベース15に設定したので、次の出力ベース設定はそのように解釈され、10₁₅= 15なので、C0₁₅からC0₁₅へのヌル変換があります。

    そうです、あなたが想定していたように、出力は16進数ではなく、15進数です!

    F0代わりに変換を試みることで、これを自分で証明できますC0F基数15に数字がないbcためE0、それをに固定E0し、出力として提供します。

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

    192

    これは、実際に使用される可能性が高い3つの例のうちの1つです。

    入力ベースを最初に16進数に変更しているため、なぜA16進数として解釈されるのかを理解するためにPOSIX仕様を詳しく調べる必要はありません。この場合は10です。唯一の問題は、デフォルト値である出力ベースをA₁₆= 10に設定することは冗長であるということです。


7

設定ibaseobaseは、同じベースで設定する必要があることを意味します。あなたの例を説明することはこれを示します:

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

bc「ibase = F」でベース15で表される入力番号を考慮するように設定します。「obase = A」は、出力番号をデフォルトの10に設定します。

bc 15を基数としてC0を読み取ります:C =12。12* 15 = 180。


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

この例では、入力を基数15に設定し、出力を基数15で10に設定しているため、出力基数は15です。基数15のC0入力は基数15のC0出力です。


echo "ibase=16;obase=A;C0" | bc

入力を基数16に設定し、出力を基数10に設定します(基数16のAは基数10で10です)。

10を基数に変換したC0は、12 * 16 = 192です。


私の個人的なルールは、ベース10を使用できるように、最初にobaseを設定することです。次に、ベース10も使用してibaseを設定します。

bc皮肉な例外があることに注意してください:ibase=Aそして、obase=A常に10を基数として入力と出力を設定しますbc。manページから:

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

この動作はbc2004 OpenGroup 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を使用して常にベースを設定することをお勧めします。混乱しないようにしてください。


@StéphaneChazelas-1989年頃にSysVr3マシンで作業していた「ibase = A」を思い出します。Single Unix Spec。以前の参考文献をすばやく検索できませんでした。
ブルースエディガー

それは、長い間使用されてきたため、古い仕様へのリンクが増えているためだと思う。apache / mysql / bugzilla ...のドキュメントでも同じようなことが起こります。Googleでは、最新バージョンではなく、古いバージョンのドキュメントを最初に提供します。
ステファンシャゼル

5

すべての数字は、GNU bcによって、その数字が現れるステートメントに有効な現在の入力ベースとして解釈されます。現在の入力以外の数字を使用する場合、数字は、複数桁の数字、または1桁の数字として使用される場合の通常の値(A== 10進数で10)。

GNUマニュアルBC

ibaseの値に関係なく、1桁の数字には常に数字の値があります。(つまり、A = 10)。複数桁の数値の場合、ibasebc以上のすべての入力桁をibase -1の値に変更します。これにより、数値は常に入力ベースの最大3桁の数値になります。FFF

ただし、POSIX標準では、との割り当てに対してのみこの動作が定義されてibaseおりobase、他のコンテキストでは定義されていないことに注意してください。

bcSUS仕様から:

ibaseまたはobaseのいずれかにbcの字句規則のリストから1 桁の値が割り当てられている場合、値は16進数であると想定されます。(例えば、IBASEベース10へ= A設定にかかわらず、現在のIBASE値。)そうでなければ、動作は場合桁より大きい未定義または値に等しいIBASE入力に現れます。ibaseobaseの両方の初期値は10です。

欠落している重要な要因は、Fが実際には16ではなく、実際には15であるため、ibase = Fを設定する場合、入力ベースを15に設定することです。

したがって、不明な状態からibaseを16進数に移植可能に設定するには、2つのステートメントを使用する必要がありますibase=A; ibase=16。ただし、プログラムの最初では、10進数であることを信頼して、単にを使用できますibase=16


+1:を使用したかわいいトリックibase=A; ibase=16
ウォーレンヤング

それはSUSv6ではなくSUSv3です。SUSv4はであるpubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html
ステファンChazelas

私はいつもヘッダーの6と7がバージョンだと思っていました。別の何かを見たことはありません-問題#1-5とは何ですか?
Random832


@WarrenYoung SUSにはPOSIXが組み込まれていませんか?この段落には拡張タグはなく、ドキュメントには「このボリュームのPOSIX.1-2008の一部」などが記載されています。
Random832

0

マニュアルページによると、などの数字ではなく、1桁の数字を設定ibaseしてobase使用することを常にお勧めします。16bc

ibaseの値に関係なく、1桁の数字は常にその数字の値を持ちます。

これはA,B,...,F、値10,11,...,15が何であるかに関係なく、常にそれぞれの値を持つことを意味しますibase。を使用F+1してnumberを指定することもできます16。たとえば、次のように書きます

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

echo "ibase=16; obase=A; C0" | bc入力ベースがで16あり、出力ベースがであることを指定するために書く代わりに10。または、たとえば、両方ibaseobase16にしたい場合は、

ibase=F+1; obase=F+1

を使用する代わりに ibase=16; obase=10。同様に、ベース14で数値を入力し、ベース16で出力する場合は、次を使用します。

ibase=E; obase=F+1

入浴フォームでも同じ結果が得られますが、前者ではエラーが発生しにくくなりますが、後者では混乱やエラーが発生する可能性があります。

2つの形式の違いは、の実行環境にいるときbc、またはファイルに計算を書き込み、そのファイルをbc引数として渡すときに特に顕著になります。このような状況で、あなたはの値に変更する必要がありますibaseし、obase数回、後者の形式を使用して、深刻な混乱とエラーにつながることができます。(それを体験してください)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.