3.2 式と算術演算子

(1/1)
演算子とオペランド
\( y = x + 3 \) というにおいて、=, + を演算子(オペレータ)、y, x, 3オペランドと呼ぶ。
今回は、四則演算子を含む算術演算子と、それを文字列に対して用いたときの働きを学ぶ。

目次

サンプル・プログラム

算術演算子

2.1 四則計算と変数」で四則演算子を紹介したが、Pythonにはそれ以外にも、べき乗関数 pow と同じ働きをするべき乗演算子 ** や、商の小数点以下を切り捨てる切り捨て除算演算子 // といった算術演算子がある。
算術演算子
演算子意味使用例
+加算1 + 2
-減算4 - 3
*乗算2 * 3
/除算3 / 2
//切り捨て除算7 // 3
%剰余算7 % 3
**べき乗算2 ** 3
除算演算子 // を使うと、西暦を世紀に変換する計算式を1行で書くことができる。
# 西暦年
year = 2024
# 西暦年から世紀を計算する
century = (year + 99) // 100
print(str(year) + "年は" + str(century) + "世紀")
なお、切り捨て除算演算子やべき乗演算子を備えていないプログラミング言語もあるので、これらは使わないほうがプログラムの移植性は高まるだろう。

では、実際に算術演算子を作ったプログラムを作り、結果をみてほしい。整数に小数を混在させたらどんな結果になるだろうか。

文字列演算子

算術演算子の一部は、文字列に対して用いることができる。実際にプログラムを作って動きを見てみよう。
a = "こんにちは"
b = "Python"
print(a + b)
すでに見てきたとおり、加算演算子 + を文字列に対し用いると、2つの文字列を結合する。
a = "12"
b = "345"
print(a + b)
数字を文字列として扱うには、このようにダブルクォーテーション(またはシングルクォーテーション)で囲めばいい。
a = 12
b = "345"
print(a + b)
数値と数字(文字列)が混在しているとエラーになってしまう。
なお、同じ動的型付け言語(後述)のJavaScriptを使って同じ式を実行すると、数値を文字列と見なして正常に結合する。逆にPHPでは、文字列を数値と見なして算術加算する。このように、同じ動的型付け言語であっても、演算子のルールが微妙に異なるので注意してほしい。

ここで応用問題だ。JavaScriptのように、数値と数字が混在しているときでも、文字列として結合させるにはどうしたらいいだろうか。プログラムを書いてみてほしい。
a = "こんにちは"
b = 3
print(a * b)
文字列 a と数値 b を乗算演算子 * にかけると、ab の回数だけ繰り返した結果の文字列を得られる。
文字列を繰り返すのにいちいち for文 を使わずに済み便利なのだが、他のプログラミング言語にはない演算子である。

練習問題

次回予告

2.4 数学関数とユーザー定義関数、入力バリデーション」で、入力バリデーションを行うのに if文を使った。そのとき、条件式に比較演算子を使った。
次回は、比較演算子と、これも if文で使うことが多い論理演算子について学ぶ。

コラム:乗算と除算ができるようになるまで

勉強しすぎの子供のイラスト(男性)
小学校の算数で、乗算に入るときに掛け算九九表を覚えさせられる。この暗記に苦労した方はいないだろうか。さらに除算となると、筆算が避けられなくなる。
じつは、コンピュータの計算を担うCPUも、最初は、四則演算のうち加算と減算しかできなかった。現在のような形になるまで、多くの技術者の苦労と工夫が積み重ねられてきたのだ。
コンピュータは2進数で動いているのだが、実際には算術計算ができるわけではなく、論理演算しかできない。
初期の8ビットCPU「Z80A」
初期の8ビットCPU「Z80A」
それは、半導体回路を使って実装できるのが論理演算回路(AND回路、OR回路、NOT回路)しかないためだ。この3つの回路の組み合わせで加算回路を作ることはできる。減算は、加数を負数とみなすことで実現できる。
ところが、乗算回路や除算回路を実装しようとすると、回路規模が極端に大きくなってしまう。つまり、CPUに搭載するトランジスタ数が膨大な数になってしまうため、初期の8ビットCPUでは乗除算回路を実装できなかった
タイガー計算機
タイガー計算機
どうやって乗算をやっていたかというと、被加数を加数の数だけ繰り返し加算するという力業だった。当然、乗算にかかる時間は、加算にかかる時間に加数を掛けただけの時間を要することになる。少しでも時間を減らそうと、加数が被加数より大きいときは、交換法則により両者を入れ替えて計算するものもあった。
除算は、さらに時間がかかった。
これらは、手動計算機であるタイガー計算機を使ってみると分かる。乗算や除算の答えを出すには、ハンドルを何回も回さなければならない。
初期の16ビットCPU「8086」
初期の16ビットCPU「8086」
8ビットCPUの数倍のトランジスタを搭載した16ビットCPUになり、ようやく、乗除算回路を搭載できた。それでも、初期の16ビットCPUであるインテル8086では、乗算は加算の約40倍、除算は約50倍の時間を要した。しかも、整数の乗除算しかできなかった。
NEC製品16ビットCPU「V30」
NEC製品16ビットCPU「V30」
1985年(昭和60年)にNECがパソコン「PC-9801」シリーズに搭載した自社製16ビットCPU「V30」は、8086互換でありながら、乗算命令の実行時間を半分以下に短縮した。こういう工夫は日本のお家芸である。
32ビットCPU「Pentium」
32ビットCPU「Pentium」
1993年(平成5年)5月に発表されたインテルの32ビットCPU「Pentium」では、小数の乗除算も実行できるようになっていたが、除算命令にバグがあるとインターネットに投稿され、いまでいう炎上騒ぎとなった。当時は、インターネットが普及したばかりで、ネット経由でBIOSやファームウェアを書き換えることができなかった。インテルは無償交換に応じざるを得ず、純利益の約2割が消し飛んだ。
一方、タブレットやスマホに搭載されているARM系のCPUは、2000年代まで乗除算に対応していなかった。ARMを含む RISC CPUは、ハードウェア回路を単純にすることでクロック数を上げることが可能になり、複雑な計算処理をソフトウェアに委ねてもハードウェア回路に引けを取らないという目算があったからだ。

乗除算を取り上げただけでも、多くの技術者の連綿と続く努力が今日のシステムを形作っていることがお分かりいただけただろうか。プログラミングを学びながら、ちょっとした息抜きの時間でいいので、コンピュータ屋ソフトウェアの開発の歴史を紐解いてほしい。今後、仕事や研究で何か難しい課題に立ち向かわなければならないとき、先達が編み出した工夫が役に立つに違いないからだ。
(この項おわり)
header