🧮

量子コンピュータでALUを作ってみた(実装編)

2024/06/17に公開

はじめに

オンライン公開伴走型量子コンピューティング講座QC4U2卒業生のluna_moonlightです。前回、ALUを量子回路で表現する方法について解説しました。前回の記事を読んでいない方は、ぜひ読んでみてください。

https://zenn.dev/luna_moonlight/articles/4b6769086788e6

今回は、前回作成した量子ALUを実際に量子コンピュータに渡して計算する方法について解説していきます。

量子コンピュータ実機

前回作成した量子回路版ALUの回路図を下に示します。これを元に早速実装していきましょう。

実装

まず、IBMの量子コンピュータを使うために、IBM Quantumでアカウントを作成します。

次に、必要な外部ライブラリをインストールしましょう。量子コンピュータを使うためにqiskit, qiskit_ibm_providerと測定結果の可視化のためにmatplotlibをインストールします。

pip install qiskit
pip install qiskit-ibm-provider
pip install matplotlib

必要な外部ライブラリをインストールしたところで、さっそくプログラムを書いていきましょう。コードの全体像はこちらです。

コードの全体像
from qiskit import QuantumCircuit, transpile
from qiskit_ibm_provider import IBMProvider


'''----------------パラメータ----------------'''
shots = 10000        # タスクを実行する回数
IBM_token = 'XXXXX'  # API token(個人のものを使用)
solver = 'ibm_kyoto' # 量子コンピュータ
'''----------------------------------------'''



# 半加算器
def HalfAdder():
    qc = QuantumCircuit(4)
    qc.ccx(0, 1, 2)
    qc.cx(0, 3)
    qc.cx(1, 3)
    
    Uhalf_adder = qc.to_gate()
    Uhalf_adder.name = "Half-Adder"
    return Uhalf_adder



# 全加算器
def FullAdder():
    HA = HalfAdder()
    qc = QuantumCircuit(8)
    qc.append(HA, [0, 1, 3, 4])
    qc.append(HA, [4, 2, 5, 7])
    qc.cx(3, 6)
    qc.cx(5, 6)
    qc.ccx(3, 5, 6)
    
    Ufull_adder = qc.to_gate()
    Ufull_adder.name = "Full-Adder"
    return Ufull_adder



# マルチプレクサ
def MUX():
    qc = QuantumCircuit(6)
    qc.ccx(1, 2, 3)
    qc.x(2)
    qc.ccx(0, 2, 4)
    qc.cx(3, 5)
    qc.cx(4, 5)
    qc.ccx(3, 4, 5)
    qc.x(2)
    
    Umux = qc.to_gate()
    Umux.name = "MUX"
    return Umux



# ALU
FA = FullAdder()
mux = MUX()

qc = QuantumCircuit(32, 2)
'''----------------入力----------------'''
# qc.x(2)       # W
# qc.x(1)       # X
# qc.x(3)       # Y
# qc.x(0)       # Z
# qc.x(7)       # A0
# qc.x(8)       # B0
# qc.x(21)      # A1
# qc.x(22)      # B1
'''-----------------------------------'''
qc.cx(1, 9)
qc.cx(8, 9)
qc.append(mux, [1, 2, 3, 4, 5, 6])
qc.append(FA, [7, 9, 6, 10, 11, 12, 13, 14])
qc.append(mux, [14, 13, 0, 15, 16, 17])
qc.cx(1, 23)
qc.cx(22, 23)
qc.append(mux, [13, 2, 3, 18, 19, 20])
qc.append(FA, [21, 23, 20, 24, 25, 26, 27, 28])
qc.append(mux, [28, 27, 0, 29, 30, 31])
qc.measure(17, 0)
qc.measure(31, 1)



# タスクの実行
provider = IBMProvider(token=IBM_token)
backend = provider.get_backend(solver)
qc = transpile(qc, backend=backend)
job = backend.run(qc, shots=shots)

ここからは、このコードを分けて解説していきます。

初期化

以下のコードは、必要なライブラリのインポートや変数、定数を定義しています。パラメータと書かれている部分を変更することで、実行回数や使う量子コンピュータを変更することができます。

from qiskit import QuantumCircuit, transpile
from qiskit_ibm_provider import IBMProvider


'''----------------パラメータ----------------'''
shots = 10000        # タスクを実行する回数
IBM_token = 'XXXXX'  # API token(個人のものを使用)
solver = 'ibm_kyoto' # 量子コンピュータ
'''----------------------------------------'''

半加算器の定義

ここでは、量子ゲートで表現した半加算器を定義しています。

# 半加算器
def HalfAdder():
    qc = QuantumCircuit(4)
    qc.ccx(0, 1, 2)
    qc.cx(0, 3)
    qc.cx(1, 3)
    
    Uhalf_adder = qc.to_gate()
    Uhalf_adder.name = "Half-Adder"
    return Uhalf_adder

全加算器の定義

ここでは、量子ゲートで表現した全加算器を定義しています。

# 全加算器
def FullAdder():
    HA = HalfAdder()
    qc = QuantumCircuit(8)
    qc.append(HA, [0, 1, 3, 4])
    qc.append(HA, [4, 2, 5, 7])
    qc.cx(3, 6)
    qc.cx(5, 6)
    qc.ccx(3, 5, 6)
    
    Ufull_adder = qc.to_gate()
    Ufull_adder.name = "Full-Adder"
    return Ufull_adder

マルチプレクサの定義

ここでは、量子ゲートで表現したマルチプレクサを定義しています。

# マルチプレクサ
def MUX():
    qc = QuantumCircuit(6)
    qc.ccx(1, 2, 3)
    qc.x(2)
    qc.ccx(0, 2, 4)
    qc.cx(3, 5)
    qc.cx(4, 5)
    qc.ccx(3, 4, 5)
    qc.x(2)
    
    Umux = qc.to_gate()
    Umux.name = "MUX"
    return Umux

ALUの定義

ここでは、量子ゲートで表現したALUを定義しています。

# ALU
FA = FullAdder()
mux = MUX()

qc = QuantumCircuit(32, 2)
'''----------------入力----------------'''
# qc.x(2)       # W
# qc.x(1)       # X
# qc.x(3)       # Y
# qc.x(0)       # Z
# qc.x(7)       # A0
# qc.x(8)       # B0
# qc.x(21)      # A1
# qc.x(22)      # B1
'''-----------------------------------'''
qc.cx(1, 9)
qc.cx(8, 9)
qc.append(mux, [1, 2, 3, 4, 5, 6])
qc.append(FA, [7, 9, 6, 10, 11, 12, 13, 14])
qc.append(mux, [14, 13, 0, 15, 16, 17])
qc.cx(1, 23)
qc.cx(22, 23)
qc.append(mux, [13, 2, 3, 18, 19, 20])
qc.append(FA, [21, 23, 20, 24, 25, 26, 27, 28])
qc.append(mux, [28, 27, 0, 29, 30, 31])
qc.measure(17, 0)
qc.measure(31, 1)

タスクの実行

ここでは、定義したALUをIBMの量子コンピュータに渡して実行しています。

# タスクの実行
provider = IBMProvider(token=IBM_token)
backend = provider.get_backend(solver)
qc = transpile(qc, backend=backend)
job = backend.run(qc, shots=shots)

結果

上のコード、つまり00_{(2)} + 00_{(2)} = 0 + 0を実行し、ステータスがcompletedになったのちに、以下のコードを実行します。

from qiskit.visualization import plot_distribution
from qiskit_ibm_provider import IBMProvider
import matplotlib.pyplot as plt


'''----------------パラメータ----------------'''
IBM_token = 'XXXXX'  # API token(個人のものを使用)
job_ID = 'XXXXX'     # 実行したジョブのID
'''----------------------------------------'''


# 結果の取得
provider = IBMProvider(token=IBM_token)
job = provider.retrieve_job(job_id=job_ID)
counts = job.result().get_counts()

# 結果の表示
plot_distribution(counts)
plt.show()

 
すると、以下のような出力が得られました。残念なことに00_{(2)} + 00_{(2)} = 0 + 0を実行したはずが、答えの00_{(2)} = 0の観測確率が一番低い結果となってしまいました。これは、量子コンピュータのノイズによるものです。現在の量子コンピュータは残念ながらノイズの影響が非常に大きく、正しい計算結果が得られません。

シミュレータ

先ほどのように、実機の量子コンピュータでは正しい結果は得られませんでした。なので、エラーのないシミュレータで前回作ったALUの計算を実行しようと思います。

実装

必要な外部ライブラリをインストールしましょう。量子コンピュータのシミュレーションを行うためにqiskit_aerを追加でインストールします。

pip install qiskit-aer

必要な外部ライブラリをインストールしたところで、さっそくプログラムを書いていきましょう。コードの全体像はこちらです。

コードの全体像
from qiskit import QuantumCircuit, transpile
from qiskit.visualization import plot_distribution
from qiskit_aer import Aer
import matplotlib.pyplot as plt


'''----------------パラメータ----------------'''
shots = 10000        # シミュレーション回数
'''----------------------------------------'''



# 半加算器
def HalfAdder():
  qc = QuantumCircuit(4)
  qc.ccx(0, 1, 2)
  qc.cx(0, 3)
  qc.cx(1, 3)
  
  Uhalf_adder = qc.to_gate()
  Uhalf_adder.name = "Half-Adder"
  return Uhalf_adder



# 全加算器
def FullAdder():
  HA = HalfAdder()
  qc = QuantumCircuit(8)
  qc.append(HA, [0, 1, 3, 4])
  qc.append(HA, [4, 2, 5, 7])
  qc.cx(3, 6)
  qc.cx(5, 6)
  qc.ccx(3, 5, 6)
  
  Ufull_adder = qc.to_gate()
  Ufull_adder.name = "Full-Adder"
  return Ufull_adder



# マルチプレクサ
def MUX():
  qc = QuantumCircuit(6)
  qc.ccx(1, 2, 3)
  qc.x(2)
  qc.ccx(0, 2, 4)
  qc.cx(3, 5)
  qc.cx(4, 5)
  qc.ccx(3, 4, 5)
  qc.x(2)
  
  Umux = qc.to_gate()
  Umux.name = "MUX"
  return Umux



# ALU
FA = FullAdder()
mux = MUX()

qc = QuantumCircuit(32, 2)
'''----------------入力----------------'''
# qc.x(2)       # W
# qc.x(1)       # X
# qc.x(3)       # Y
# qc.x(0)       # Z
# qc.x(7)       # A0
# qc.x(8)       # B0
# qc.x(21)      # A1
# qc.x(22)      # B1
'''-----------------------------------'''
qc.cx(1, 9)
qc.cx(8, 9)
qc.append(mux, [1, 2, 3, 4, 5, 6])
qc.append(FA, [7, 9, 6, 10, 11, 12, 13, 14])
qc.append(mux, [14, 13, 0, 15, 16, 17])
qc.cx(1, 23)
qc.cx(22, 23)
qc.append(mux, [13, 2, 3, 18, 19, 20])
qc.append(FA, [21, 23, 20, 24, 25, 26, 27, 28])
qc.append(mux, [28, 27, 0, 29, 30, 31])
qc.measure(17, 0)
qc.measure(31, 1)



# シミュレーションの実行
simulator = Aer.get_backend('qasm_simulator')
qc = transpile(qc, simulator)
job = simulator.run(qc, shots=shots)
counts = job.result().get_counts(qc)



# 結果の表示
plot_distribution(counts)
plt.show()

ここからは、このコードを分けて解説していきます。

初期化

以下のコードは、必要なライブラリのインポートや変数、定数を定義しています。パラメータと書かれている部分を変更することで、シミュレーションの実行回数を変更することができます。

from qiskit import QuantumCircuit, transpile
from qiskit.visualization import plot_distribution
from qiskit_aer import Aer
import matplotlib.pyplot as plt


'''----------------パラメータ----------------'''
shots = 10000        # シミュレーション回数
'''----------------------------------------'''

半加算器の定義

ここでは、量子ゲートで表現した半加算器を定義しています。これは、実機量子コンピュータのときと変わりません。

# 半加算器
def HalfAdder():
    qc = QuantumCircuit(4)
    qc.ccx(0, 1, 2)
    qc.cx(0, 3)
    qc.cx(1, 3)
    
    Uhalf_adder = qc.to_gate()
    Uhalf_adder.name = "Half-Adder"
    return Uhalf_adder

全加算器の定義

ここでは、量子ゲートで表現した全加算器を定義しています。これは、実機量子コンピュータのときと変わりません。

# 全加算器
def FullAdder():
    HA = HalfAdder()
    qc = QuantumCircuit(8)
    qc.append(HA, [0, 1, 3, 4])
    qc.append(HA, [4, 2, 5, 7])
    qc.cx(3, 6)
    qc.cx(5, 6)
    qc.ccx(3, 5, 6)
    
    Ufull_adder = qc.to_gate()
    Ufull_adder.name = "Full-Adder"
    return Ufull_adder

マルチプレクサの定義

ここでは、量子ゲートで表現したマルチプレクサを定義しています。これは、実機量子コンピュータのときと変わりません。

# マルチプレクサ
def MUX():
    qc = QuantumCircuit(6)
    qc.ccx(1, 2, 3)
    qc.x(2)
    qc.ccx(0, 2, 4)
    qc.cx(3, 5)
    qc.cx(4, 5)
    qc.ccx(3, 4, 5)
    qc.x(2)
    
    Umux = qc.to_gate()
    Umux.name = "MUX"
    return Umux

ALUの定義

ここでは、量子ゲートで表現したALUを定義しています。これは、実機量子コンピュータのときと変わりません。

# ALU
FA = FullAdder()
mux = MUX()

qc = QuantumCircuit(32, 2)
'''----------------入力----------------'''
# qc.x(2)       # W
# qc.x(1)       # X
# qc.x(3)       # Y
# qc.x(0)       # Z
# qc.x(7)       # A0
# qc.x(8)       # B0
# qc.x(21)      # A1
# qc.x(22)      # B1
'''-----------------------------------'''
qc.cx(1, 9)
qc.cx(8, 9)
qc.append(mux, [1, 2, 3, 4, 5, 6])
qc.append(FA, [7, 9, 6, 10, 11, 12, 13, 14])
qc.append(mux, [14, 13, 0, 15, 16, 17])
qc.cx(1, 23)
qc.cx(22, 23)
qc.append(mux, [13, 2, 3, 18, 19, 20])
qc.append(FA, [21, 23, 20, 24, 25, 26, 27, 28])
qc.append(mux, [28, 27, 0, 29, 30, 31])
qc.measure(17, 0)
qc.measure(31, 1)

シミュレーションの実行

ここでは、定義したALUのシミュレーションを実行し、結果を取得しています。

# シミュレーションの実行
simulator = Aer.get_backend('qasm_simulator')
qc = transpile(qc, simulator)
job = simulator.run(qc, shots=shots)
counts = job.result().get_counts(qc)

結果の表示

ここでは、実行結果をヒストグラムで表示しています。

# 結果の表示
plot_distribution(counts)
plt.show()

結果

上のコードを実行すると以下のようなエラーが出てしまいました。前回作成したALUは32qubits使用しています。しかし、30qubitsまでしかtranspileできないためこのようなエラーが発生してしまいました。

qiskit.transpiler.exceptions.TranspilerError: 'Number of qubits (32) in circuit-167 is greater than maximum (30) in the coupling_map'

ビット数削減

先ほどのエラーを解消するために、2qubitsの削減を行なっていきます。前回作成したALUの量子回路をみると、B \oplus Xの計算後にBは使っていません。なので、B \oplus Xの結果を別のqubitに保存せずに、Bを直接書き換えてしまっても問題ありません。B_0B_1に対してこの削減を行うことで、ALUを30qubitsで表現できます。

XORゲート

先ほど紹介したXORゲートは、CXゲートを使って下のように表せます。

計算すると下のようになり、確かにXORゲートの結果と一致しています。

行列計算

A=0, B=0のとき

CX_{0, 1}\ket{00}= \begin{pmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0\\ \end{pmatrix} \begin{pmatrix} 1\\ 0\\ 0\\ 0\\ \end{pmatrix}= \begin{pmatrix} 1\\ 0\\ 0\\ 0\\ \end{pmatrix} =\ket{00}

A=0, B=1のとき

CX_{0, 1}\ket{01}= \begin{pmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0\\ \end{pmatrix} \begin{pmatrix} 0\\ 1\\ 0\\ 0\\ \end{pmatrix}= \begin{pmatrix} 0\\ 1\\ 0\\ 0\\ \end{pmatrix} =\ket{01}

A=1, B=0のとき

CX_{0, 1}\ket{10}= \begin{pmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0\\ \end{pmatrix} \begin{pmatrix} 0\\ 0\\ 1\\ 0\\ \end{pmatrix}= \begin{pmatrix} 0\\ 0\\ 0\\ 1\\ \end{pmatrix} =\ket{11}

A=1, B=1のとき

CX_{0, 1}\ket{11}= \begin{pmatrix} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 1\\ 0 & 0 & 1 & 0\\ \end{pmatrix} \begin{pmatrix} 0\\ 0\\ 0\\ 1\\ \end{pmatrix}= \begin{pmatrix} 0\\ 0\\ 1\\ 0\\ \end{pmatrix} =\ket{10}
A_{in} B_{in} A_{out} A \oplus B(B_{out})
0 0 0 0
0 1 0 1
1 0 1 1
1 1 1 0

ALU

先ほどのXORゲートを使ってALUのビット数を削減すると下のように表せます。

 
これに伴ってプログラムのALU定義部分を以下のように変更します。これで準備が整ったので、早速ALUの計算をしてみましょう。

# ALU
FA = FullAdder()
mux = MUX()

qc = QuantumCircuit(30, 2)
'''----------------入力----------------'''
# qc.x(2)       # W
# qc.x(1)       # X
# qc.x(3)       # Y
# qc.x(0)       # Z
# qc.x(7)       # A0
# qc.x(8)       # B0
# qc.x(20)      # A1
# qc.x(21)      # B1
'''-----------------------------------'''
qc.cx(1, 8)
qc.append(mux, [1, 2, 3, 4, 5, 6])
qc.append(FA, [7, 8, 6, 9, 10, 11, 12, 13])
qc.append(mux, [13, 12, 0, 14, 15, 16])
qc.cx(1, 21)
qc.append(mux, [12, 2, 3, 17, 18, 19])
qc.append(FA, [20, 21, 19, 22, 23, 24, 25, 26])
qc.append(mux, [26, 25, 0, 27, 28, 29])
qc.measure(16, 0)
qc.measure(29, 1)

加算

01_{(2)} + 01_{(2)} = 1 + 1を計算してみましょう。加算の際の入力はW=*, X=0, Y=0, Z=0なので、プログラムの入力部分を以下のように変更して実行します。

# qc.x(2)       # W
# qc.x(1)       # X
# qc.x(3)       # Y
# qc.x(0)       # Z
qc.x(7)       # A0
qc.x(8)       # B0
# qc.x(20)      # A1
# qc.x(21)      # B1

すると、以下のような出力が得られました。100\%の確率で10_{(2)} = 2となっており、正しく加算が行えていそうです。

減算

00_{(2)} - 01_{(2)} = 0 - 1を計算してみましょう。減算の際の入力はW=*, X=1, Y=0, Z=0なので、プログラムの入力部分を以下のように変更して実行します。

# qc.x(2)       # W
qc.x(1)       # X
# qc.x(3)       # Y
# qc.x(0)       # Z
# qc.x(7)       # A0
qc.x(8)       # B0
# qc.x(20)      # A1
# qc.x(21)      # B1

すると、以下のような出力が得られました。100\%の確率で11_{(2)} = -1となっており、正しく減算が行えていそうです。

bitwise AND

11_{(2)} \cdot 10_{(2)}を計算してみましょう。ANDの際の入力はW=0, X=0, Y=1, Z=1なので、プログラムの入力部分を以下のように変更して実行します。

# qc.x(2)       # W
# qc.x(1)       # X
qc.x(3)       # Y
qc.x(0)       # Z
qc.x(7)       # A0
# qc.x(8)       # B0
qc.x(20)      # A1
qc.x(21)      # B1

すると、以下のような出力が得られました。100\%の確率で10_{(2)}となっており、正しくbitwise ANDが計算できていそうです。

bitwise OR

01_{(2)} + 00_{(2)}を計算してみましょう。ORの際の入力はW=1, X=0, Y=1, Z=1なので、プログラムの入力部分を以下のように変更して実行します。

qc.x(2)       # W
# qc.x(1)       # X
qc.x(3)       # Y
qc.x(0)       # Z
qc.x(7)       # A0
# qc.x(8)       # B0
# qc.x(20)      # A1
# qc.x(21)      # B1

すると、以下のような出力が得られました。100\%の確率で01_{(2)}となっており、正しくbitwise ORが計算できていそうです。

bitwise XOR

11_{(2)} \oplus 10_{(2)}を計算してみましょう。XORの際の入力はW=0, X=0, Y=1, Z=0なので、プログラムの入力部分を以下のように変更して実行します。

# qc.x(2)       # W
# qc.x(1)       # X
qc.x(3)       # Y
# qc.x(0)       # Z
qc.x(7)       # A0
# qc.x(8)       # B0
qc.x(20)      # A1
qc.x(21)      # B1

すると、以下のような出力が得られました。100\%の確率で01_{(2)}となっており、正しくbitwise XORが計算できていそうです。

bitwise XNOR

\overline{10_{(2)} \oplus 11_{(2)}}を計算してみましょう。XNORの際の入力はW=1, X=0, Y=1, Z=0なので、プログラムの入力部分を以下のように変更して実行します。

qc.x(2)       # W
# qc.x(1)       # X
qc.x(3)       # Y
# qc.x(0)       # Z
# qc.x(7)       # A0
qc.x(8)       # B0
qc.x(20)      # A1
qc.x(21)      # B1

すると、以下のような出力が得られました。100\%の確率で10_{(2)}となっており、正しくbitwise XNORが計算できていそうです。

重ね合わせ入力

せっかくなので、量子コンピュータらしいことをしてみましょう。試しに、重ね合わせ状態でANDの計算をしてみましょう。この演算を行うには、プログラムの入力部分を以下のように変更して実行します。W, X, Y, Zについては、通常のANDの時と同様です。A, Bに対してXゲートではなくHゲートを適用しています。

# qc.x(2)       # W
# qc.x(1)       # X
qc.x(3)       # Y
qc.x(0)       # Z
qc.h(7)       # A0
qc.h(8)       # B0
qc.h(20)      # A1
qc.h(21)      # B1

すると、以下のような出力が得られました。56.2\%, 18.8\%, 18.5\%, 6.5\%の確率で00_{(2)}, 01_{(2)}, 10_{(2)}, 11_{(2)}となっており、A \cdot Bから求めた理想の確率に近い値が得られていることがわかりました。

00_{(2)} 01_{(2)} 10_{(2)} 11_{(2)}
理想 \dfrac{9}{16} = 56.25\% \dfrac{3}{16} = 18.75\% \dfrac{3}{16} = 18.75\% \dfrac{1}{16} = 6.25\%
結果 56.2\% 18.8\% 18.5\% 6.5\%
真理値表
A B A \cdot B
00_{(2)} 00_{(2)} 00_{(2)}
00_{(2)} 01_{(2)} 00_{(2)}
00_{(2)} 10_{(2)} 00_{(2)}
00_{(2)} 11_{(2)} 00_{(2)}
01_{(2)} 00_{(2)} 00_{(2)}
01_{(2)} 01_{(2)} 01_{(2)}
01_{(2)} 10_{(2)} 00_{(2)}
01_{(2)} 11_{(2)} 01_{(2)}
10_{(2)} 00_{(2)} 00_{(2)}
10_{(2)} 01_{(2)} 00_{(2)}
10_{(2)} 10_{(2)} 10_{(2)}
10_{(2)} 11_{(2)} 10_{(2)}
11_{(2)} 00_{(2)} 00_{(2)}
11_{(2)} 01_{(2)} 01_{(2)}
11_{(2)} 10_{(2)} 10_{(2)}
11_{(2)} 11_{(2)} 11_{(2)}

まとめ

この記事では、前回作成した量子ALUを実際に量子コンピュータに渡して計算する方法について解説しました。残念ながら、実機の量子コンピュータではエラーが非常に多く、正しく計算できているかわからなかったので、シミュレータでの計算方法についても解説しました。ぜひ自分でも入力値をいじって遊んでみてください。

Discussion