3

Radix Pointに関するウィキペディアの記事を考えると、10.1 に相当する 2 進数または 17.17 に相当する 16 進数をどのように計算しますか? 前者の場合、10 分の 1 に相当する 2 進数は何ですか? 後者の場合、17/100 の 16 進数表現は?

私は、これら 2 つの例の解決策よりもアルゴリズムを探しています。

4

5 に答える 5

6

10進数の10.1を2進数に変換するには、整数部分と小数部分を分離し、それぞれを別々に変換します。

整数部分を変換するには、2による整数除算を繰り返してから、余りを逆の順序で書き込みます。

10/2=5剰余0

5/2=2剰余1

2/2=1剰余0

1/2=0剰余1

回答:1010

小数部分を変換するには、2を繰り返し乗算し、各ステップで整数部分を減算します。整数部分は、生成順に、2進数を表します。

0.1 * 2 = 0.2

0.2 * 2 = 0.4

0.4 * 2 = 0.8

0.8 * 2 = 1.6

0.6 * 2 = 1.2

0.2 * 2 = 0.4

0.4 * 2 = 0.8

...(サイクルは永遠に繰り返されます)

したがって、10進数の0.1は2進数の0.000110011001100です。

(より詳細な説明については、私の記事http://www.exploringbinary.com/base-conversion-in-php-using-bcmath/のルーチンdec2bin_i()およびdec2bin_f()を参照してください。)

16進数の場合は、2ではなく16の除数/乗数を使用することを除いて、同じ手順を使用します。9より大きい剰余と整数部分は、16進数に直接変換する必要があります。10はAになり、11はBになり、...、15はFになります。 。

于 2009-05-31T19:26:03.730 に答える
3

基数b 1 の終端数(有限桁数で表すことができる数)n 1 は異なる基数の非終端数になる可能性がある。逆に、1つの基数b1の非終端数は、基数b の終端数であることが判明する場合がある。

2 進数に変換した場合の 0.1 10は、16 進数に変換した場合の0.17 10と同様に、終了しない数値です。しかし、基数 3 の終了数 0.1 3は、基数 10 に変換すると、非終了の繰り返し数 0.(3) 10になります (数 3 が繰り返されることを意味します)。同様に、0.1 10を 2 進数に変換し、0.17 10を 16 進数に変換すると、0.0(0011) 2と 0.2(B851E) 16の繰り返される非終了の数値になります。

このため、このような数値をある基数から別の基数に変換する場合、完全に正確な表現ではなく、数値を概算する必要があることに気付く場合があります。

于 2009-05-31T16:37:13.517 に答える
3

アルゴリズムは非常に単純ですが、実際にはルックアップ テーブルとログの両方で多くの微調整を行って高速化できます。ただし、基本的なアルゴリズムについては、次のようなものを試すことができます。

shift=0;

while v>=base,  v=v/base, shift=shift+1;  

Next digit: 
if v<1.0 && shift==0, output the decimal point
else 
   D=floor(v)
   output D
   v=v-D
v=v*base
shift = shift-1
if (v==0) exit;
goto Next Digit

10 進数をより長く繰り返すために、N 桁の後に印刷を停止するテストをそこに入れることもできます。

于 2009-05-31T15:59:05.973 に答える
1

10 分の 1 の「2 進法」は 2 分の 1 です。つまり、1/10^1 ではなく、1/2^1 です。

各桁は 2 の累乗を表します。基数の後ろの数字は同じですが、1 の 2 乗を表しているだけです。

 8 4 2 1 . 1/2 1/4 1/8 1/16 

したがって、10.1 の場合、10 の部分を作成するには、明らかに「8」と「2」が必要です。1/2 (0.5) は多すぎます。1/4 (0.25) は多すぎます。1/8 (0.125) は多すぎます。1/16 (0.0625) が必要なので、残りは 0.0375 です。1/32 は 0.03125 なので、それも取ることができます。これまでのところ、次のことがわかっています。

 8 4 2 1 . 1/2 1/4 1/8 1/16 1/32
 1 0 1 0    0   0   0   1     1

0.00625 の誤差があります。1/64 (0.015625) と 1/128 (0.0078125) はどちらも大きすぎます。1/256 (0.00390625) が機能します。

 8 4 2 1 . 1/2 1/4 1/8 1/16 1/32 1/64 1/128 1/256
 1 0 1 0    0   0   0   1     1    0   0     1

0.00234375 の誤差があります。

.1 は 2 進数で正確に表現できません (1/3 を 10 進数で正確に表現できないのと同様)。基数を置く場所に応じて、最終的には停止し、おそらく丸め、エラーを受け入れる必要があります。

于 2009-05-31T16:31:08.217 に答える
0

私の GMP ライブラリーに照らしてこれをいじる前に、Rick Regan の PHP コードを 2 から 36 までの任意の基数に対して汎用的にしようとしたところです。

Function dec2base_f(ByVal ddecimal As Double, ByVal nBase As Long, ByVal dscale As Long) As String
    Const BASES = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" 'up to base 36
    Dim digitCount As Long
    Dim wholeNumber As Double
    Dim digit As String * 1
    digitCount = 0
    dscale = max(dscale, Len(CStr(ddecimal)) - Len("0."))
    Dim baseary_f As String
    baseary_f = "0."
    Do While ddecimal > 0 And digitCount < dscale
        ddecimal = ddecimal * nBase
        digit = Mid$(BASES, Fix(ddecimal) + 1)
        baseary_f = baseary_f & digit '"1"
        ddecimal = ddecimal - Fix(ddecimal)
        digitCount = digitCount + 1
    Loop
    dec2base_f = baseary_f
End Function

Function base2dec_f(ByVal baseary_f As String, nBase As Double) As Double
    Const BASES As String = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    Dim decimal_f As Double
    Dim i As Long
    Dim c As Long
    For i = Len(baseary_f) To Len("0.") + 1 Step -1
        c = InStr(BASES, Mid$(baseary_f, i, 1)) - 1
        decimal_f = decimal_f + c
        decimal_f = decimal_f / nBase
    Next
    base2dec_f = decimal_f
End Function

Debug.Print base2dec_f(dec2base_f(0.09, 2, 200), 2) --> 0.09
Debug.Print base2dec_f(dec2base_f(0.09, 8, 200), 8) --> 0.09
Debug.Print base2dec_f(dec2base_f(0.09, 16, 200), 16) --> 0.09
于 2009-06-01T14:26:13.050 に答える