paiza レベルアップ問題集 「STEP: 5 10 進数から 2 進数に変換」をPythonとGASで解いてみた

この記事を読むことで、PythonとGASで10進数から2進数に基数変換するコードの書き方を学べ、whileやForループの書き方、スライスを使った書き方、剰余演算子、リスト(配列の追加)など、プログラミングの基幹となる文法の習得を強化できます。

whileループで2で割った余りをリスト(配列)に格納し、Pythonではスライスを使ってForループでリストの逆順から表示させます。

別解として2進数に変換した計算結果をansという変数に格納するコードも記述しました。GASではこの別解に基づいてコードを書いています。

このコーナーでは、学習コンテンツpaizaラーニングレベルアップ問題集をPythonとGASの両方で解いて全コードの解説をしています。
PythonとGASの両方のコードを用いて、全コード及び部分的にも可能な限り詳細に記載いたしました。

GASはスプレッドシートを使っています。
GASはGoogle Apps Scriptと言って、JavaScriptの文法をベースにしているので、JavaScriptの学習中の方にもお役立て出来るかも知れません。

サイトマップはこちらから

paizaレベルアップ問題集でPythonとGASを解いて見たに戻る
メインメニューに戻る
Python自作サンプル
GASサンプル
基本情報技術者試験

paizaでの解答はPythonで行いましたが、この記事ではPythonのコードと共に、同じ問題を現在学習中のGASだったらどう解くのか、スプレッドシートでバインドして作ってみました。

10 進数から 2 進数に変換 (paizaランク D 相当)

10 進数で表された整数 N が与えられます。
N を 2 進数に変換して出力してください。

この記事では、下記の入力例3の場合、10進数N=10が与えられた時に2進数でどのように変化していくかを求めて行きます。

入力例3
10

出力例3
1010

ではまず、Pythonで解いてみます。

今回は、paiza.ioを使って解きます。paiza.ioの使い方はこちらから。

■ Pythonでの解き方 ■

下準備として、paiza.ioにこの様に入力します。
(入力例1をそのままioにコピーしただけ。)

手順として、

1:10進数の数値N=10を取得する

2:余りを格納する整数arrayを宣言する

3:whileループでN>=1の間、2で割り続けて余りをarrayに格納する

4:Forループでスライスを使ってarrayを逆順に取り出す

で、行います。

10進数を2進数に基数変換をする時は、下記のような2で割った余りを求めて、下から記述する方法で計算しました。
これは、10進数の10を2進数の「1010」に変換する時の計算過程です。

この図では、10を2で割った余りが「0」、5を2で割った余りが「1」、2を2で割った余りは「0」、最後1が残ります。
この余りを下から上に向かって「1010」と書くことで10進数の10を2進数の「1010」に変換出来ました。

この計算過程をwhileループを使って行います。
余りは配列arrayに順次追加して行きます。

まずは、プログラムの各変数の動きを追いやすいように、トレースのio出力結果と、トレースのコードを添えます。
Whileループのトレースをします。

1回目の除算

2回目の除算

3回目の除算

4回目の除算

余りを格納したリストをForループでスライスを使って逆から取り出しました。
以上を踏まえて、トレースのコードを掲載します。

#10進数の整数Nを取得する
N=int(input())

#余りを格納するリストarrayを宣言する
array=[]

#whileループでN>=1の間、2で割り続けて余りをarrayに格納する

print('<<<ループに入る>>>')

while N>=1:
    print('除算前のリストarray:'+str(array))
    print('除算前のNの値:'+str(N))
    array.append(N%2)
    print('格納する余り:「'+str(N%2)+'」')
    
    N/=2
    N=int(N)
    print('除算後のNの値:'+str(N))
    print('除算後リストarray:'+str(array))
    print('------------------------')


print('<<<ループを抜ける>>>')    

#arrayを表示する
print(array)

#Forループを使って逆順から取り出す
for num in array[::-1]:
    print(num,end="")

#ループを抜けた所で改行をする
print()

このままでは、出力結果である出力例3に対して冗長なコードが含まれているので、解答以外のprint文をコメントアウトします。

#10進数の整数Nを取得する
N=int(input())

#余りを格納するリストarrayを宣言する
array=[]

#whileループでN>=1の間、2で割り続けて余りをarrayに格納する

#print('<<<ループに入る>>>')

while N>=1:
    #print('除算前のリストarray:'+str(array))
    #print('除算前のNの値:'+str(N))
    array.append(N%2)
    #print('格納する余り:「'+str(N%2)+'」')
    
    N/=2
    N=int(N)
    #print('除算後のNの値:'+str(N))
    #print('除算後リストarray:'+str(array))
    #print('------------------------')


#print('<<<ループを抜ける>>>')    

#arrayを表示する
#print(array)

#Forループを使って逆順から取り出す
for num in array[::-1]:
    print(num,end="")

#ループを抜けた所で改行をする
print()

スッキリするように、コメントアウトした部分を省いたコードです。

#10進数の整数Nを取得する
N=int(input())

#余りを格納するリストarrayを宣言する
array=[]

while N>=1:
    array.append(N%2)

    N/=2
    N=int(N)

#Forループを使って逆順から取り出す
for num in array[::-1]:
    print(num,end="")

#ループを抜けた所で改行をする
print()

ioの出力結果です。

上記ではスライスを使ってリストをForループで逆から取り出していましたが、リストを反転させて、[1,0,1,0]を1010と表記させる方法のコードを掲載します。

この部分を別解のコードでは、[1,0,1,0]を1010になるようにansという変数を使って、Forループで計算しています。

ansの初期値は0で10倍すると0、
そこにリストから「1」を加えると「ans=1」になります。
ans=1を10倍すると10、そこにリストから「0」を加えて「ans=10」になります。
ans=10を10倍すると100、そこにリストから「1」を加えて「101」になります。
ans=101を10倍すると1010、そこにリストから「0」を加えて「1010」になります。

そのForループのトレースと、コメントアウトをしたコード、コメントアウトを取り除いたコードを掲載します。

ループに入る前にリストを反転します。

1回目のansの計算

2回目のansの計算

3回目のansの計算

4回目のansの計算

以上を踏まえて、トレースのコードを掲載します。

#10進数の整数Nを取得する
N=int(input())

#余りを格納するリストarrayを宣言する
array=[]

while N>=1:
    array.append(N%2)

    N/=2
    N=int(N)

#リストarrayを出力
print(array)

#リストarrayを反転させる
array=list(reversed(array))

#反転させたリストarrayを出力
print(array)

#基数変換の計算結果を格納する変数ansを0で初期化
ans=0

#Forでリスト内の数を基数変換した形式で表示する

print('<<<Forループに入ります。>>>')

for num in array:
    print('計算前のans:'+str(ans))
    ans*=10
    print('10倍したans:'+str(ans))
    ans+=num
    print('計算後のans:'+str(ans))
    print('-------------------')

print('<<<Forループを抜けました>>>')


#基数変換の計算結果ansを表示させる
print(ans)

冗長な部分をコメントアウトしたコードです。

#10進数の整数Nを取得する
N=int(input())

#余りを格納するリストarrayを宣言する
array=[]

while N>=1:
    array.append(N%2)

    N/=2
    N=int(N)

#リストarrayを出力
#print(array)

#リストarrayを反転させる
array=list(reversed(array))

#反転させたリストarrayを出力
#print(array)

#基数変換の計算結果を格納する変数ansを0で初期化
ans=0

#Forでリスト内の数を基数変換した形式で表示する

#print('<<<Forループに入ります。>>>')

for num in array:
    #print('計算前のans:'+str(ans))
    ans*=10
    #print('10倍したans:'+str(ans))
    ans+=num
    #print('計算後のans:'+str(ans))
    #print('-------------------')

#print('<<<Forループを抜けました>>>')


#基数変換の計算結果ansを表示させる
print(ans)

更にトレース部分のコメント部分を削除したコードです。


#10進数の整数Nを取得する
N=int(input())

#余りを格納するリストarrayを宣言する
array=[]

while N>=1:
    array.append(N%2)
    N/=2
    N=int(N)


#リストarrayを反転させる
array=list(reversed(array))

#基数変換の計算結果を格納する変数ansを0で初期化
ans=0


#Forでリスト内の数を基数変換した形式で表示する

for num in array:
    ans*=10
    ans+=num

#基数変換の計算結果ansを表示させる
print(ans)

別解でも無事正解しました。

■ GASでの解き方 ■

では、同じ問題をGASで解いてみます。
まず、スプレッドシートにこの様に配置しました。

スプレッドシートの黄色いセルの所に「10進数N(=10)を2進数に基数変換をした結果1010」を出力します。
基数変換の計算結果はansに格納します。
また、ansを二次元配列ans2に追加して、スプレッドシートに出力します。

※スプレッドシートに表示する場合は、ループを使って一次元配列ではなく、二次元配列としてからの配列に追加をして作成します※

手順はこのようになります。

1:スプレッドシートからアクティブシートをアクセスする

2:スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する


3:2で割った余りを格納する配列を宣言する


4:whileループを使って余りを配列に格納する


5:配列を表示


6:配列を反転させる


7:反転した配列を表示


8:2進数を変数ansに格納する為、ansを0で初期化する

9:ループで2進数を計算する

10:ansを表示

11:スプレッドシートに格納する二次元配列ans2を宣言

12:ansをans2に二次元配列として格納

13:スプレッドシートに出力前にans2を出力して確認する

14:スプレッドシートの黄色い所に2進数に基数変換した結果を格納する

手順1: スプレッドシートからアクティブシートをアクセスする

const ss=SpreadsheetApp.getActiveSheet();

ここで定数ssにSpreadsheetAppから階層を辿ってアクティブシートにアクセスしています。

手順2:スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する

let N=ss.getRange(1,2).getValue();

※Nを2で割っていくので、Nの値が変わる、すなわち変数なので定数のconstではなく変数のletで宣言をします※

手順3:2で割った余りを格納する配列を宣言する

let array=[]

手順4:whileループを使って余りを配列に格納する

1回目の除算

2回目の除算

3回目の除算

4回目の除算

whileループのコードの部分です。

//whileループを使って余りを配列に格納する

  console.log('<<<whileループに入る>>>');

  while(N>=1){
    console.log(`除算前のNの値:${N}`);
    console.log(`除算前の配列array[${array}]`);
    //配列に余りを追加する
    array.push(N%2);
    console.log(`余り:${N%2}`);
    //除算実行
    N/=2;
    //小数点を切り捨てる
    N=Math.floor(N);
    
    console.log(`除算後のNの値:${N}`);
    console.log(`除算前の配列array[${array}]`);
    console.log('--------------------');

  }

  console.log('<<<whileループを抜けました。>>>');

手順5:配列を表示

console.log(array);

手順6:配列を反転させる

array=array.reverse();

手順7:反転した配列を表示

console.log(array);

配列の反転前と反転後のログです。

手順8:2進数を変数ansに格納する為、ansを0で初期化する

let ans=0;

手順9:Forループで2進数に基数変換する

1回目のansの計算

2回目のansの計算

3回目のansの計算

4回目のansの計算

Forループの部分のコードです。

console.log('<<<Forループに入る>>>');

  //ループで2進数を計算する
  for(let i=0;i<=array.length-1;i++){
    console.log(`計算前のansの値:${ans}`);
    ans*=10;
    console.log(`10倍したansの値:${ans}`);
    ans+=array[i];
    console.log(`計算後のansの値:${ans}`);
    console.log('---------------------------');
  }

  console.log('<<<Forループを抜けました。>>>');

手順10:ansを表示

console.log(ans);

手順11:スプレッドシートに格納する二次元配列ans2を宣言

let ans2=[];

手順12:ansをans2に二次元配列として格納

ans2.push([ans]);

手順13:スプレッドシートに出力前にans2を出力して確認する

console.log(ans2);

手順14:スプレッドシートの黄色い所に2進数に基数変換した結果を格納する

ss.getRange(3,2).setValue(ans2);

GASでの全コードはこちらになります。

function loop2no10(){

  //スプレッドシートからアクティブシートをアクセスする
  const ss=SpreadsheetApp.getActiveSheet();


  //スプレッドシートの緑色のセルから10進数の整数N(この例では「10」)を取得する
  let N=ss.getRange(1,2).getValue();

  
  //2で割った余りを格納する配列を宣言する
  let array=[]
  
  
  //whileループを使って余りを配列に格納する

  console.log('<<<whileループに入る>>>');

  while(N>=1){
    console.log(`除算前のNの値:${N}`);
    console.log(`除算前の配列array[${array}]`);
    //配列に余りを追加する
    array.push(N%2);
    console.log(`余り:${N%2}`);
    //除算実行
    N/=2;
    //小数点を切り捨てる
    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);

  //2進数を変数ansに格納する為、ansを0で初期化する
  let ans=0;

  console.log('<<<Forループに入る>>>');

  //ループで2進数を計算する
  for(let i=0;i<=array.length-1;i++){
    console.log(`計算前のansの値:${ans}`);
    ans*=10;
    console.log(`10倍したansの値:${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);

  //スプレッドシートの黄色い所に2進数に基数変換した結果を格納する
  ss.getRange(3,2).setValue(ans2);

}

宜しかったらコピペしてアレンジして見て下さい。
お疲れ様でした、ブレイクタイムフォトはこちらになります。

みなとみらいの海と夜景

■ 参考文献の紹介■

じっくり丁寧にPythonを学びたい方向け。
まずはpaizaラーニングなどの学習コンテンツで学んで、基礎をマスターしたら、この本でじっくりと初級から中級レベルを目指せます。

初めてGASを学ぶ方向け。
スプレッドシートの基本的な使い方からGASのベースとなるJavaScriptの基礎文法、GASでの初歩的なプログラミングを学べます。

GASに少し慣れて来たら、基礎固めとリファレンスとしてこの本でじっくり学べます。

サイトマップはこちらから

paizaレベルアップ問題集でPythonとGASを解いて見たに戻る
メインメニューに戻る
Python自作サンプル
GASサンプル
基本情報技術者試験

←前の問題へ          次の問題へ→

投稿者: nekosiestr

プログラミング学習中のロスジェネ(就職氷河期世代)の発達障害者です。 宜しくお願いします。 趣味で写真を撮っています。 プログラミングは、GAS/HTML/CSS/JavaScript/jQuery/PHP、 発達障害は、自閉症スペクトラムASD/ADHD、その他双極性障害やHSP(5人に1人の繊細さん)などの生きづらさを抱えておりますが、それでも楽しく生きて行きたいです!! 写真は、以前はコンパクトデジカメ、現在は、OLYMPUSミラーレス一眼を使っています。

モバイルバージョンを終了