基数10を経由せずに基数から基数に変換する背後にある数学は?


36

任意のベースから任意のベースへの変換の背後にある数学を調べてきました。これは、何よりも結果の確認に関するものです。mathforum.orgで私の答えと思われるものを見つけましたが、正しいかどうかはまだわかりません。大規模なベースから小規模なベースへの変換は大丈夫です。なぜなら、最初の桁に次の桁の繰り返しを追加したいだけであるためです。私の問題は、小さなベースから大きなベースに変換するときに発生します。これを行うとき、彼らはあなたがあなたが持っている小さなベースに必要な大きなベースを変換する必要があるかについて話します。たとえば、ベース4からベース6に移動すると、6をベース4に変換して12を取得する必要があります。その後、大から小に変換するときと同じことを行います。私がこれに関して持っている難しさは、あなたが他のベースにある数字が何であるかを知る必要があるようです。したがって、ベース4に6が何であるかを知る必要があります。テーブルが必要になるため、これは私の頭に大きな問題を引き起こします。誰もがこれをより良い方法で行う方法を知っていますか?

基本的な変換が役立つと思いましたが、そのような機能が見つかりません。そして、私が見つけたサイトから、ベース10を経由せずにベースからベースに変換できるようですが、最初にベースからベースに最初の数値を変換する方法を知る必要があります。それはちょっと無意味になります。

コメンターは、文字を数字に変換する必要があると言っています。もしそうなら、私はすでにそれを知っています。しかし、それは私の問題ではありません。私の問題は、大きなベースを小さなベースに変換するために、最初に持っているベース番号を必要なベース番号に変換する必要があることです。これらのベースを他のベースに変換する能力があれば、すでに問題を解決しているので、これを行うことで目的を無効にします。

編集:10以下のベースから10以下の他のベースに変換する方法を考えました。10以上のベースから10以下のベースに移動することもできます。この問題は、10を超えるベースから10を超えるベースに変換するときに開始されます。または、10未満のベースから10を超えるベースに移行すると、コードが不要になります。コードに適用されます。


1
このフォーラムのトピックに関する質問ですか?
アンドレイバウアー

2
ターゲットベースで加算と乗算を実行できる限り、手順は簡単です。できないなら、それは可能だとは思わない。
カロリスジュデリー

9
グリフィンは、多くの生徒が聞く必要があることを最初に伝える必要があります。数値は、ベースに表されずに存在します。それから答えは明確です:与えられたベースの数の表現を数に変換するアルゴリズム(つまり、を取り、string返すものint)、および数を取り、その表現を返すアルゴリズムが必要です与えられたベースで。
アンドレイバウアー

1
@AndrejBauer質問はCSについてです。たとえそのように表現されていなくても、これは数値表現間で変換するアルゴリズムに関する質問です。[無関係なメモ:紛らわしいコメントをたくさん削除しました。グリフィン:質問を編集して更新してください。その他:チャットに持って行ってください。]
ジル「SO-悪であるのをやめ

1
@グリフィンそれはあなたの元の質問から長い時間です。答えを見つけていただければ幸いです。もしそうなら、更新して回答を受け入れるか、あなたの回答を投稿するのは素晴らしいアイデアかもしれません。それまでの間、GoogleのCode Jam Archivesで非常に素晴らしいアイデア(C ++での実装について話している)をいくつか見つけました。この問題のいくつかの解決策は非常に創造的ですcode.google.com/codejam/contest/32003/dashboard
IsaacCisneros

回答:


45

これは私にとって非常に基本的な質問のように思えますので、少し教えてください。ここで学ぶための最も重要な点は、数字は数字表現ではないということです。数字は抽象的な数学的なオブジェクトですが、数字表現は具体的なものです。つまり、紙の上の記号のシーケンス(または計算メモリのビットのシーケンス、または数字を伝えるときに作る音のシーケンス)です。紛らわしいのは、数字は表示されず、常に数字が表示されるという事実です。そのため、数字表現であると考えることになります。

したがって、尋ねる正しい質問は、「あるベースから別のベースに変換する方法」ではなく、「特定の数字列によってどの数字が表されているかをどのように調べますか」および「与えられた番号」。

そこで、Pythonで2つの関数を作成します。1つは数字表現を数値に変換し、もう1つはその逆を行います。注:私たちは、コースの機能Pythonの意志実行画面上のプリントを、それがベース10に入った数をしかし、これはないではないコンピュータが(それはない)ベース10の数値を維持していることを意味します。コンピューターが数字をどのように表すかは関係ありません

def toDigits(n, b):
    """Convert a positive number n to its digit representation in base b."""
    digits = []
    while n > 0:
        digits.insert(0, n % b)
        n  = n // b
    return digits

def fromDigits(digits, b):
    """Compute the number given by digits in base b."""
    n = 0
    for d in digits:
        n = b * n + d
    return n

これらをテストしましょう:

>>> toDigits(42, 2)
[1, 0, 1, 0, 1, 0]
>>> toDigits(42, 3)
[1, 1, 2, 0]
>>> fromDigits([1,1,2,0],3)
42

変換機能を備えているため、問題は簡単に解決できます。

def convertBase(digits, b, c):
    """Convert the digits representation of a number from base b to base c."""
    return toDigits(fromDigits(digits, b), c)

テスト:

>>> convertBase([1,1,2,0], 3, 2) 
[1, 0, 1, 0, 1, 0]

注: 10進表記を通過しませんでした!基数表現を数値に変換してから、数値を基数変換しました。番号はどの表現にもありませんでした。(実際には、コンピューターは何らかの方法でそれを表現する必要があり、チップで発生する電気信号とファンキーなものを使用してそれを表現しましたが、確かにそれらは0でも1でもありませんでした。)bc


4
これは私を100%納得させません。実際、コンピューターはプラトニックな数学者ではなく、アルゴリズムはベース任意の数字シーケンスをベース変換できないため、数値を何らかの表現に変換しました(それが何であるかわからないと主張することはできますが)。具体的なマシンで表現可能なシーケンスのみを変換できます。Pythonは魅力的に柔軟です。Cはそれほど寛容ではなかったでしょう。任意の文字列をからに変換する方法を尋ねることは完全に有効です。ただし、これは特定のベースの組み合わせ(例:2 <-> 16)を除き、線形時間でのみ可能ですb1b2b1b2
リチ

1
質問をすることは有効ですが、正しい答えを見つけるには、数字が抽象的なエンティティであるという事実を認識することが最善です。
アンドレイバウアー

2
これ、基数10の数値をfromDigits返すため、基数10の表現を通して数値を渡します。
aporton13年

8
@anorton:いいえ、間違いなくそうではありませ。Pythonは画面上に10進数で数字を表示しますが、数字自体はそのように保存されません。私が理解しようとしているのは、数値がPython内でどのように実装されているかは関係ないということです。それはどうでもいい事です。重要なのは、数字のように振る舞うことだけです。
アンドレイバウアー

3
最後に、特定のユースケース、36未満のベース、または十分な一意のシンボルを思いつくインスタンスに限定されない、あらゆるベースの一般的なソリューション。
J.Money

21

これを理解するための最良の方法は、エイリアンと議論することです(少なくとも類推として)。

定義 は基数数値で、は数字のストリングあることを意味します。xbx<b

数字の文字列10010011011は2を底とする数字、68416841531は10を底とする数字、BADCAFEは16を底とする数字です。

今、私は誰もがして仕事に教えられている惑星QUUXで育ったと彼らの一生のために、そして私がベースに使用されている方、あなたを満たす。それで、あなたは私に番号を見せて、私は何をしますか?私はそれを解釈する方法が必要です:qb

定義次の式により、基数数値(注:は基数数値)を解釈できます。bbq

[[ϵ]]=0[[s¯d]]=[[s¯]]×b+d

ここで、は空の文字列を示し、は数字終わる文字列を示します。この表記法の概要については、追加によって追加されるという私の証拠を参照しください。ϵs¯dd

ここで何が起こったのでしょうか?あなたは私にベース数を与えました、そして、私はそれをベース解釈しました、数が本当に何であるかについての奇妙な哲学なしで。bq

キーこれのキーは、と Iがベース数で動作する関数であることです。これらは、ベース番号(数字列)に再帰的に定義された単純なアルゴリズムです。×+qq


私はずっと実際の数字ではなく変数を使ってきたので、これは少し抽象的に見えるかもしれません。あなたがベース13クリーチャー(シンボルを使用)であり、シンボル使用してベース7(はるかに賢明)に慣れているとします。0123456789XYZαβγδρζξ

だから私はあなたのアルファベットを見て、それを表にまとめました:

0α1β2γ3δ4ρ5ζ6ξ7βα8ββ9βγXβδYβρZβζ

βξ

60Z8

[[60Z8]]=ξ(βξ)3+α(βξ)2+βζ(βξ)+ββ

βζ×βξ

九乗表

×βγδρζξββγδρζξγγρξβββδβζδδξβγβζγβγρρρβββζγγγξδδζζβδγβγξδρργξξβζγρδδργζββαβαγαδαραζαξα

βζ×βξ

βζ×βξξγρβζδβγγ

だから私はここまで持っています

[[60Z8]]=ξ(βξ)3+α(βξ)2+βζ(βξ)+ββ=ξ(βξ)3+α(βξ)2+δβγ+ββ

ここで、前述のアルゴリズムを使用して追加を実行する必要があります。

δβγββδγδ

そう

[[60Z8]]=ξ(βξ)3+α(βξ)2+βζ(βξ)+ββ=ξ(βξ)3+α(βξ)2+δβγ+ββ=ξ(βξ)3+α(βξ)2+δγδ

[[60Z8]]=ζδξγρ.

qbq


1
まあ、それはかなりの波線でした。どうすればコンピューターにそれをさせることができますか?
グリフィン

1
@グリフィン、あなたはその(奇妙な)質問を時期尚早に求めていると思います。プログラミング言語を選択し、ベースq数(数字のリストとして表される)での加算と乗算のアルゴリズムを入力し、ベースb数字をベースq数に変換し、ベースb数をベースq数に変換する関数を定義します。これをすべて説明しました。

あなたが描写しようとしている概念を知っています。私の問題は、私のコンピューターが波線を使用できないことです。
グリフィン

あなたが説明したことは知っていますが、それを実践するのははるかに困難です。これらの数字を定義するのは簡単ではありません。
グリフィン

1
また、なぜアルファ桁を最も重要な位置に落としたのですか?6 =&xi;なので、7 =α&alpha;ではないでしょうか?
ジョヴァンニボッタ14

9

これはAndrejのコードのリファクタリング(Python 3)です。Andrejのコード番号は、数字のリスト(スカラー)で表されますが、次のコード番号では、カスタム文字列から取得したシンボルのリストで表されます

def v2r(n, base): # value to representation
    """Convert a positive number to its digit representation in a custom base."""
    b = len(base)
    digits = ''
    while n > 0:
        digits = base[n % b] + digits
        n  = n // b
    return digits

def r2v(digits, base): # representation to value
    """Compute the number represented by string 'digits' in a custom base."""
    b = len(base)
    n = 0
    for d in digits:
        n = b * n + base[:b].index(d)
    return n

def b2b(digits, base1, base2):
    """Convert the digits representation of a number from base1 to base2."""
    return v2r(r2v(digits, base1), base2)

カスタムベースで値から表現への変換を実行するには:

>>> v2r(64,'01')
'1000000'
>>> v2r(64,'XY')
'YXXXXXX'
>>> v2r(12340,'ZABCDEFGHI') # decimal base with custom symbols
'ABCDZ'

表現(カスタムベース)から値への変換を実行するには:

>>> r2v('100','01')
4
>>> r2v('100','0123456789') # standard decimal base
100
>>> r2v('100','01_whatevr') # decimal base with custom symbols
100
>>> r2v('100','0123456789ABCDEF') # standard hexadecimal base
256
>>> r2v('100','01_whatevr-jklmn') # hexadecimal base with custom symbols
256

ある顧客ベースから別の顧客ベースへのベース変換を実行するには:

>>> b2b('1120','012','01')
'101010'
>>> b2b('100','01','0123456789')
'4'
>>> b2b('100','0123456789ABCDEF','01')
'100000000'

1
このサイトへようこそ、あなたの貢献に感謝します。ただし、最適化されたソースコードを作成することは、このサイトの目的ではありません。Andrejのコードは概念を明確にします。これは彼の答えに必要なものですが、それ以上のコードの改善はコンピューターサイエンスではなくプログラミングの問題です。
デビッドリチャービー16年

1
@DavidRicherby部分的には同意しますが、この投稿はコメントするには長すぎたため、Andrejの答えに近いのが最適な場所であるため、ここに投稿しました。とにかくそれが良いと思うなら、コードへのリンクを含むコメントに変換できますが、それは過剰な純粋主義ではないでしょうか?
mmj

1

基本変換の基本操作はtoDigits()、@ AndrejBauer answerの操作です。ただし、それを行うために、数値の内部表現に数値を作成する必要はありません。これは基本的に、基数2表現からの変換です。元のベース表現で必要な操作を行うことができます。

したがって、最初のステップは、モジュロ除算を繰り返し行うことです

def convertBase(n,original_base,destination_base):
    digits = []    
    while not is_zero(n):
        digits.insert(0,modulo_div(n,original_base,destination_base))
    return digits

内部表現は数字であるため、ゼロをテストするために指定された関数を作成する必要があります

def is_zero(n):
    for d in n:
        if d != 0:
            return False
    return True

最終的にはmodulo_div操作を作成する必要がありますが、これは実際に学校で学んだように、宛先ベースによる標準的な分割です。

def modulo_div(n,original_base,destination_base):
    carry = 0
    for i in range(len(n)):
        d = n[i]
        d+=original_base*carry 
        carry = d%destination_base 
        d=(d//destination_base)
        n[i] = d
        #print(i,d,carry)
    return carry

コードが正しいことを確認するためのテストチェックのみ:

print(convertBase([1,1,2,0], 3, 2))
#[1, 0, 1, 0, 1, 0]

print(convertBase([1, 0, 1, 0, 1, 0], 2, 3))
#[1, 1, 2, 0]

投稿していただきありがとうございますが、私たちはコーディングサイトではないため、ここでの回答として大きなコードブロックは適切ではありません。特に、質問に「コードは必要なく、その背後にある基本的な数学が必要なだけです」と明示されている場合は特にそうです。
デビッドリチャービー

@DavidRicherbyテキストを追加しようとしました。
ザビエルコンベル

ありがとう。そして、私が言ったことにもかかわらず、このページにはたくさんのコードがあります!
デビッドリチャービー

0

コンピュータープログラムを必要としない基本変換を行う簡単な方法を知っています。任意のベースからベース2へ、またはその逆に変換する方法を定義し、最初に最初のベースからベース2に変換し、次にベース2から他のベースに変換することにより、あるベースから別のベースに変換します。2は、任意のベースで乗算または除算が非常に簡単です。

任意の基数から基数2に変換するには、基数2の表記法を使用して0から開始し、左から右へ順番に各数字がゼロである場合に任意の数で任意の数字を認識し、その数字が1の場合、1を加算するよりも倍になり、その数値自体に到達します。任意の基数でその数を指定すると、その基数で2で除算して商と剰余を取得できます。剰余が1の場合、最後の2進数は1で、剰余が0の場合、最後の2進数は0です。再び2で除算します。剰余が1の場合、最後から2番目の桁は1で、余りが0の場合、最後から2番目の桁は0となり、商が0になるまで続きます。

基数2から任意の基数に変換するには、その基数で、0から始まり、左から右へ行く各2進数字について、その数字が0の場合はその基数で2倍し、その中に1を追加するだけですその数字が1の場合、ベース。


2 is so easy to multiply or divide by in any base.2の累乗(最初は11と13)から1を超える奇数のベースについてはわかりません。
greybeard

0

中間ベースに変換せずに、ベースnからベース10に変換できます。

たとえば、ベースnからベース9に変換するには、ベース10に変換するアルゴリズムを使用して、「10」を「9」に置き換えます。他のベースでも同じです。

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