この記事を読むことで、PythonとGASで10進数から任意の進数(M進数)に基数変換するコードの書き方を学べます。
whileループでMで割った余りをリスト(配列)に格納し、Pythonではスライスを使ってForループでリストの逆順から表示させます。
別解として2進数に変換した結果を数値に格納するコードも記述しました。
GASではこの別解に基づいてコードを書いています。
基本的なループの書き方にスライスを使った書き方、剰余演算子、リスト(配列の追加)など、プログラミングの基幹となる文法の習得を強化できます。
このコーナーでは、学習コンテンツpaizaラーニングのレベルアップ問題集をPythonとGASの両方で解いて全コードの解説をしています。
PythonとGASの両方のコードを用いて、全コード及び部分的にも可能な限り詳細に記載いたしました。
GASはスプレッドシートを使っています。
GASはGoogle Apps Scriptと言って、JavaScriptの文法をベースにしているので、JavaScriptの学習中の方にもお役立て出来るかも知れません。
paizaレベルアップ問題集でPythonとGASを解いて見たに戻る
メインメニューに戻る
Python自作サンプル
GASサンプル
基本情報技術者試験
paizaでの解答はPythonで行いましたが、この記事ではPythonのコードと共に、同じ問題を現在学習中のGASだったらどう解くのか、スプレッドシートでバインドして作ってみました。
10 進数から M 進数に変換 (paizaランク C 相当)
問題:
10 進数で表された整数 N, M が与えられます。
N を M 進数に変換して出力してください。
この記事では、下記の入力例2の場合に、10進数N=10と基数変換するM進数M=8が与えられた時に、8進数でどのような計算結果になるのかを求めて行きます。
入力例2
10 8
出力例2
12
ではまず、Pythonで解いてみます。
今回は、paiza.ioを使って解きます。paiza.ioの使い方はこちらから。
■ Pythonでの解き方 ■
下準備として、paiza.ioにこの様に入力します。
(入力例1をそのままioにコピーしただけ。)
手順として、
1:10進数の数値N=10とM進数のM=8を取得する
2:余りを格納する整数arrayを宣言する
3:whileループでN>=1の間、Mで割り続けて余りをarrayに格納する
4:Forループでスライスを使ってarrayを逆順に取り出す
で、行います。
まずは、プログラムの各変数の動きを追いやすいように、トレースのio出力結果と、トレースのコードを添えます。
10進数の10を8進数に変換すると12になり、計算過程はこちらの画像をご覧下さい。
この計算をwhileループを使って行います。
では、Whileループのトレースをします。
1回目の除算
2回目の除算
以上を踏まえて、トレースの部分を表示したコードを掲載します。
#10進数の整数NとM進数のMを取得
N,M=map(int,input().rstrip().split(' '))
#余りを格納するリストを宣言
array=[]
#NがM以上の場合に除算を繰り返して余りをリストに格納する
print('<<<ループに入る>>>')
while N>=1:
print('除算実行前のNの値:'+str(N))
print('除算実行前のリストarray:'+str(array))
#NをMで除算して、余りをarrayに格納する
array.append(N%M)
#リストに格納する余り
print('リストに追加した余り【'+str(N%M)+'】')
#除算してNを更新する
N/=M
#Nを整数にする
N=int(N)
print('除算実行後のNの値:'+str(N))
print('除算実行後のリストarray:'+str(array))
print('-----------------------')
print('<<<ループを抜けた>>>')
#リストを表示
print(array)
#リストを逆順から取り出す
for num in array[::-1]:
print(num,end="")
print()
このままでは、出力結果である出力例3に対して冗長なコードが含まれているので、解答以外のprint文をコメントアウトします。
#10進数の整数NとM進数のMを取得
N,M=map(int,input().rstrip().split(' '))
#余りを格納するリストを宣言
array=[]
#NがM以上の場合に除算を繰り返して余りをリストに格納する
#print('<<<ループに入る>>>')
while N>=1:
#print('除算実行前のNの値:'+str(N))
#print('除算実行前のリストarray:'+str(array))
#NをMで除算して、余りをarrayに格納する
array.append(N%M)
#リストに格納する余り
#print('リストに追加した余り【'+str(N%M)+'】')
#除算してNを更新する
N/=M
#Nを整数にする
N=int(N)
#print('除算実行後のNの値:'+str(N))
#print('除算実行後のリストarray:'+str(array))
#print('-----------------------')
#print('<<<ループを抜けた>>>')
#リストを表示
#print(array)
#リストを逆順から取り出す
for num in array[::-1]:
print(num,end="")
print()
更に、コードがスッキリするように、コメントアウトした部分を省いたコードです。
#10進数の整数NとM進数のMを取得
N,M=map(int,input().rstrip().split(' '))
#余りを格納するリストを宣言
array=[]
#NがM以上の場合に除算を繰り返して余りをリストに格納する
while N>=1:
#NをMで除算して、余りをarrayに格納する
array.append(N%M)
#除算してNを更新する
N/=M
#Nを整数にする
N=int(N)
#リストを逆順から取り出す
for num in array[::-1]:
print(num,end="")
print()
ioの出力結果です。
上の書き方ではスライスを使ってリストをForループで逆から取り出していましたが、リストを反転させて、[1,2]を12と表記させる方法のコードを掲載します。
別解のコードでは、Forループのトレースと、コメントアウトをしたコード、コメントアウトを取り除いたコードを掲載します。
#10進数の整数NとM進数のMを取得
N,M=map(int,input().rstrip().split(' '))
#余りを格納するリストを宣言
array=[]
#NがM以上の場合に除算を繰り返して余りをリストに格納する
while N>=1:
#NをMで除算して、余りをarrayに格納する
array.append(N%M)
#除算してNを更新する
N/=M
#Nを整数にする
N=int(N)
#リストを反転させる
print(array)
array=list(reversed(array))
print(array)
#8進数を格納する変数ansを0で初期化
ans=0
print()
#リストの数値を元に計算結果をansに格納
print('<<<Forループに入る>>>')
for num in array:
print('計算前のansの値:'+str(ans))
ans*=10
print('10倍したansの値:'+str(ans))
print(str(ans)+'に'+str(num)+'を加える')
ans+=num
print('計算後のansの値'+str(ans))
print('-----------------')
print('<<<Forループを抜けた>>>')
print()
print(ans)
For文に入る前に、リストを反転させます。
では、For文のループでの変数の動きを見て行きます。
1回目のansの計算
2回目のansの計算
このコードを出力形式に合わせてコメントアウトしたコードです。
#10進数の整数NとM進数のMを取得
N,M=map(int,input().rstrip().split(' '))
#余りを格納するリストを宣言
array=[]
#NがM以上の場合に除算を繰り返して余りをリストに格納する
while N>=1:
#NをMで除算して、余りをarrayに格納する
array.append(N%M)
#除算してNを更新する
N/=M
#Nを整数にする
N=int(N)
#リストを反転させる
#print(array)
array=list(reversed(array))
#print(array)
#8進数を格納する変数ansを0で初期化
ans=0
#print()
#リストの数値を元に計算結果をansに格納
#print('<<<Forループに入る>>>')
for num in array:
#print('計算前のansの値:'+str(ans))
ans*=10
#print('10倍したansの値:'+str(ans))
#print(str(ans)+'に'+str(num)+'を加える')
ans+=num
#print('計算後のansの値'+str(ans))
#print('-----------------')
#print('<<<Forループを抜けた>>>')
#print()
print(ans)
更に、コメント部分を取り除いた、スッキリとしたコードです。
#10進数の整数NとM進数のMを取得
N,M=map(int,input().rstrip().split(' '))
#余りを格納するリストを宣言
array=[]
#NがM以上の場合に除算を繰り返して余りをリストに格納する
while N>=1:
#NをMで除算して、余りをarrayに格納する
array.append(N%M)
#除算してNを更新する
N/=M
#Nを整数にする
N=int(N)
#リストを反転させる
array=list(reversed(array))
#8進数を格納する変数ansを0で初期化
ans=0
for num in array:
ans*=10
ans+=num
print(ans)
別解でも無事正解しました。
■ GASでの解き方 ■
では、同じ問題をGASで解いてみます。
まず、スプレッドシートにこの様に配置しました。
スプレッドシートの黄色いセルの所に「10進数N(=10)をM(=8)進数に基数変換をした結果12」を出力します。
基数変換の計算結果はansに格納します。
また、ansを二次元配列ans2に追加して、スプレッドシートに出力します。
※スプレッドシートに表示する場合は、ループを使って一次元配列ではなく、二次元配列としてからの配列に追加をして作成します※
手順はこのようになります。
1:スプレッドシートからアクティブシートをアクセスする
2:スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する
3:スプレッドシートの灰色のセルからM進数のM(この例では「8」)を取得する
4:8で割った余りを格納する配列を宣言する
5:whileループを使って余りを配列に格納する
6:配列を表示
7:配列を反転させる
8:反転した配列を表示
9:M進数を変数ansに格納する為、ansを0で初期化する
10:Forループで8進数を計算する
11:ansを表示
12:スプレッドシートに格納する二次元配列ans2を宣言
13:ansをans2に二次元配列として格納
14:スプレッドシートに出力前にans2を出力して確認する
15:スプレッドシートの黄色い所に8進数に基数変換した結果を格納する
手順1: スプレッドシートからアクティブシートをアクセスする
const ss=SpreadsheetApp.getActiveSheet();
ここで定数ssにSpreadsheetAppから階層を辿ってアクティブシートにアクセスしています。
手順2:スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する
let N=ss.getRange(1,2).getValue();
※Nを割っていくので、Nの値が変わる、すなわち変数なので定数のconstではなく変数のletで宣言をします※
手順3:スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する
let N=ss.getRange(1,2).getValue();
手順4:2で割った余りを格納する配列を宣言する
let array=[]
手順5:whileループを使って余りを配列に格納する
1回目の除算
2回目の除算
whileループの部分のコードです。
//whileループを使って余りを配列に格納する
console.log('<<<whileループに入りました>>>');
while(N>=1){
console.log(`計算前のNの値:${N}`);
console.log(`計算前の配列array:[${array}]`);
console.log(`配列に追加する余り【${N%M}】`);
//配列に追加
array.push(N%M);
//割り算の実行
N/=M;
//Nを整数にする
N=Math.floor(N);
console.log(`計算後のNの値:${N}`);
console.log(`計算後の配列array:[${array}]`);
console.log('------------------------');
}
console.log('<<<whileループを抜けました。>>>');
手順6:配列を表示
console.log(array);
手順7:配列を反転させる
array=array.reverse();
手順8:反転した配列を表示
console.log(array);
配列を反転させる前と後の画像です。
手順9:2進数を変数ansに格納する為、ansを0で初期化する
let ans=0;
手順10:Forループでリストから2進数に基数変換する
1回目のansの計算
2回目のansの計算
Forループのコードです。
//Forループで8進数を計算する
console.log('<<<Forループに入りました>>>');
for(let i=0;i<=array.length-1;i++){
//配列の値をansに計算する
console.log(`計算前のansの値:${ans}`);
ans*=10;
console.log(`ansを10倍にした値:${ans}`);
ans+=array[i];
console.log(`計算後のansの値:${ans}`);
console.log('------------------------');
}
console.log('<<<Forループを抜けました。>>>');
手順11:ansを表示
console.log(ans);
手順12:スプレッドシートに格納する二次元配列ans2を宣言
let ans2=[];
手順13:ansをans2に二次元配列として格納
ans2.push([ans]);
手順14:スプレッドシートに出力前にans2を出力して確認する
console.log(ans2);
手順15:スプレッドシートの黄色い所に8進数に基数変換した結果を格納する
ss.getRange(3,2).setValue(ans2);
実行した後のスプレッドシートです。
GASでの全コードはこちらになります。
function loop2no11() {
//スプレッドシートからアクティブシートをアクセスする
const ss = SpreadsheetApp.getActiveSheet();
//スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する
let N = ss.getRange(1, 2).getValue();
//スプレッドシートの灰色のセルからM進数のM(この例では「8」)を取得する
const M = ss.getRange(2, 2).getValue();
//8で割った余りを格納する配列を宣言する
let array = [];
//whileループを使って余りを配列に格納する
console.log('<<<whileループに入りました>>>');
while (N >= 1) {
console.log(`計算前のNの値:${N}`);
console.log(`計算前の配列array:[${array}]`);
console.log(`配列に追加する余り【${N % M}】`);
//配列に追加
array.push(N % M);
//割り算の実行
N /= M;
//Nを整数にする
N = Math.floor(N);
console.log(`計算後のNの値:${N}`);
console.log(`計算後の配列array:[${array}]`);
console.log('------------------------');
}
console.log('<<<whileループを抜けました。>>>');
//配列を表示
console.log(array);
//配列を反転させる
array = array.reverse();
//反転した配列を表示
console.log(array);
//M進数を変数ansに格納する為、ansを0で初期化する
let ans = 0;
//Forループで8進数を計算する
console.log('<<<Forループに入りました>>>');
for (let i = 0; i <= array.length - 1; i++) {
//配列の値をansに計算する
console.log(`計算前のansの値:${ans}`);
ans *= 10;
console.log(`ansを10倍にした値:${ans}`);
ans += array[i];
console.log(`計算後のansの値:${ans}`);
console.log('------------------------');
}
console.log('<<<Forループを抜けました。>>>');
//ansを表示
console.log(ans);
//スプレッドシートに格納する二次元配列ans2を宣言
let ans2 = [];
//ansをans2に二次元配列として格納
ans2.push([ans]);
//スプレッドシートに出力前にans2を出力して確認する
console.log(ans2);
//スプレッドシートの黄色い所に8進数に基数変換した結果を格納する
ss.getRange(4, 2).setValue(ans2);
}
宜しかったらコピペしてアレンジして見て下さい。
お疲れ様でした、ブレイクタイムフォトはこちらになります。
神奈川県川崎市、工場地帯の工場萌え写真。
■ 参考文献の紹介■
じっくり丁寧にPythonを学びたい方向け。
まずはpaizaラーニングなどの学習コンテンツで学んで、基礎をマスターしたら、この本でじっくりと初級から中級レベルを目指せます。
初めてGASを学ぶ方向け。
スプレッドシートの基本的な使い方からGASのベースとなるJavaScriptの基礎文法、GASでの初歩的なプログラミングを学べます。
GASに少し慣れて来たら、基礎固めとリファレンスとしてこの本でじっくり学べます。
paizaレベルアップ問題集でPythonとGASを解いて見たに戻る
メインメニューに戻る
Python自作サンプル
GASサンプル
基本情報技術者試験