Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

10進数をn進数へ変換する[python]

初めに

・初心者が勉強を兼ねてやってるのでご指導いただけるとありがたいです。
・n進数の説明が序盤あるので知ってる人は読まなくてもいいです

10進数とは

僕たちの世界では基本的に10進数という概念で数字を扱っています。
例えば
1234という数字は
... + 10000*0 + 1000*1 + 100*2 + 10*3 + 1*4 という意味を持ち
10のべき乗数である、[1,10,100,1000,10000,......]を省略するという意味です。
(頭の0も省略してますけど)

この省略というのがミソで省略せずに数字を表す「漢字」で「1234」を書くと

千二百二十四と書くのがだるいんですよね。(見るのもだるい)

10のべき乗数を省略して書くというのは数学史における大発明の一つであると思います。
(アインシュタインの略記法もアインシュタインが残した一番の発明と呼ばれてたりしますし、便利すぎる略記法は凄いんだなあ(小並感))

n進数とは

ただ数学が進歩するにつれ数学者たちは一般化にロマンを求めるようになりました(ロマンは求めてないと思います)
この数の表記法の一般化を考え始めたんですね。
なら10のべき乗数ではなくnのべき乗数を省略したらどうなるんだろう?
それがn進数という概念です。

n進数のルール

まず基本的なルールとしては10進数世界と同じです。
ただ、意識してなかったかもしれないルールがあります。
それは
「nのべき乗の係数はn未満である必要がある」
というもの。
2進数世界で
a*4を考えるとき
a=3だったら
(2+1)*4
=8+1*4となり8が現れますよね?
これは繰り上がりの意味を持ちます。
計算途中で繰り上がりが出るのならわかりますが
数字の表記上で繰り上がりが出るのは嫌ですよね。もちろん、繰り上がりを認める表記法も存在するかもしれませんが、繰り上がりを認めると数の表記が一意に定まりません(二通り以上存在するということ)

例えば9という数は2進数表記だと
1*8+0*4+0*2+1*1なので1001と表記できます。
しかし、繰り上がりを認めると
0*8+1*4+2*2+1*1=121
2はこの世界では10と表記されるので
121=1(10)1となり1001と違う書き方になってしまい9を二つの方法で表してしまいます。
これを認める数学の世界はもちろん作れるでしょうが、
「係数はn未満」って条件つけるだけで一意に定まるんだからその条件を使いましょう。
そっちのほうが便利なので。
(よく考えてないけどwelldefinedとか絡んできたらめんどくさいですし)

プログラムの解説

好きな進数に変換するプログラムを作りますが、今回は各係数をリストで返すことにします。
理由は100進数とかに変換したいとき、係数の87とかが見えやすいようにです。
もっと具体例で解説すると
「8765」は100進数表記で
(87)(65)となります。((87)で1桁の数字になる)
ただ見えにくいのでリストで[87,65]と表記することにします。
意味は87*100+65*1ですね。

プログラムの流れ

まず変換したい数を10進数で入力して、変換したい進数を入力してもらいます。

N=int(input())#変換したい10進数の値
K=int(input())#進数

あ、一応関数にします

def change(N,shinsu):

そして返すリストの準備からします。
変換後の桁数が分かると楽なのでまず桁数を求めます

    keta=0
    for i in range(10**9):
        if N<shinsu**i:
             keta+=i
             break

これで変換後の桁数が分かりました。
つまり返すリストのサイズが分かったのでリストを準備します。

    ans=[0]*keta

あとは頭からK^xの係数を求めるだけです。

    for i in range(1,keta+1):
        j=N//(shinsu**(keta-i))
        ans[check]=j
        check+=1
        N-=(j)*(shinsu**(keta-i))

最後に返せば終わりです

    return ans

一つにまとめると

N=int(input())#変換したい10進数の値
K=int(input())#進数

def change(N,shinsu):
    keta=0
    for i in range(10**9):
        if N<shinsu**i:
             keta+=i
             break
    ans=[0]*keta
    check=0
    for i in range(1,keta+1):
        j=N//(shinsu**(keta-i))
        ans[check]=j
        check+=1
        N-=(j)*(shinsu**(keta-i))
    return ans

print(change(N,K))

これで完成です!

遊んでみた

1023
2
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
9765624
5
[4, 4, 4, 4, 4, 4, 4, 4, 4, 4]
2853116705
11
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

n進数を10進数へ

逆にn進数のリストが与えられたらそれを10進数に復元する関数も作っておきます。

def henkan(list,shinsu):
    l=len(list)
    ans=0
    for i in range(1,l+1):
        ans+=list[-i]*(shinsu**(i-1))
    return ans

まとめ

個人的に16進数をA,B,C,D,E,Fを用いて表すのに抵抗があったので作成しました。
プログラムの練習で作った関数で結構お気に入りの関数です。
ご指導ご鞭撻よろしくお願いします><

nprimem
分類上一応理系の大学生. プログラムは最近始めました.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away