今回は脱線からさらに脱線をして、負の整数における剰余
のあたりを見ていく回にしますね。
こちらの話題はもともと自分の中で評判な技術ブログ「その Swift コード、こう書き換えてみないか」を眺めてみているときに、剰余を使ったコードでのエッジケースとして出てきた条件式から気になった話題で、そういえば主催者自身、負の値を扱うときの 剰余
の動きを把握できていないことに気がついたので、この機にそれに着目して学習していってみます。よろしくお願いしますね。
———————————————————————————————————— 熊谷さんのやさしい Swift 勉強会 #257
00:00 開始 00:09 今回は、負の値に対する剰余の話 01:30 負の値に対する剰余、馴染みある? 03:35 負の値に対する剰余 05:27 剰余計算のもうひとつの発想 08:58 剰余として、正と負のどちらが適切か 12:35 負の値に対する剰余 14:27 言語によって方針が異なる 15:36 Swift での負の剰余の扱い 17:30 isMultiple(of:) も符号を加味して判断する様子 19:30 クロージングと次回の展望 ————————————————————————————————————
Transcription & Summarize : 熊谷さんのやさしい Swift 勉強会 #257
今日は負の値に対する剰余の演算について話しました。これは前から個人的に興味があるテーマで、特に他の人のコードを書き換える際に見かけたエッジケースとして興味を引きました。負の値に対する剰余はあまり馴染みがないかもしれませんが、調べてみるといろいろと面白い話が見つかります。
まず、正の値を用いた剰余を考えてみましょう。例えば、100を7で割った場合の剰余は 100 % 7
です。これは計算すれば簡単に出てきますね。しかし、これは100を7で割ったときの余りで、結果は2です。次に、100を-7で割った場合はどうでしょうか?同じように計算すると、結果は2になります。
負の値の場合も同様に考えられます。例えば、-100を7で割った場合の剰余を考えてみましょう。この場合は余りが-2になります。同じように、-100を-7で割るとどうなるでしょうか?計算すると、余りは-2になります。このように、負の値に対する剰余の計算も基本的には正の値と同じルールが適用されます。
この計算過程において、負の値に対しても剰余は一定のルールに従っています。たとえば、100を-7で割る場合、その商は-14となります。そして、100は -7 * -14 + 2
と表されます。同様に、-100を7で割る場合も -14 * 7 + (-2)
となります。
こうした計算は一見取っつきにくいかもしれませんが、ルールを押さえておけば意外と理解しやすいです。賛否はあるかもしれませんが、プログラミングにおいてはこうしたエッジケースを理解しておくことが重要です。
剰余の計算は一般的には整数同士の割り算に対して行われますが、言語や環境によっては動作が異なることもあります。理解を深めるためには、実際にコードを書いて試してみるのが一番です。
今回の話題を踏まえて、負の値に対する剰余の扱い方についてもう少し詳しく勉強してみましょう。プログラミングの世界では、こうした細かい点も理解しておくと、いざというときに役立ちます。この勉強会を通じて、皆さんが理解を深めてくれることを期待しています。
今日はこの話題を中心に進めてきましたが、これからも興味深いトピックを取り上げていきたいと思います。次回も楽しみにしてください。 とりあえずこれも成り立つわけですよ。マイナスで終わったからといって問題があるわけではないです。ちょっと考えてみましょう。マイナス100を7で割った余りがいくつになるかという話です。
例えば、ここでは -100 % 7
の計算を考えてみます。これは -100
に近い 7
の倍数は -105
なので、-100 % 7
の余りは 5
になります。ただし、7
を -15
として計算すると、答えは変わってきます。ここで重要なのは、どのように余りを考えるかです。結果として 5
になる可能性もあります。
余りを負の数とする場合もあります。例えば、-100
を 7
で割った余りを -2
にすることも可能です。この考え方には馴染みが薄いかもしれませんが、高等教育を受けていれば自然に考えられる可能性もあります。「2個足りない」という表現を用いることで、負の数の概念を理解しやすくする方法もあるかもしれません。
負の数というのは、人間にとってはある程度馴染みがあるかもしれませんが、動物には理解できない概念です。ゼロやマイナスというのも昔は難しい概念でした。
Swiftの場合、-100 % 7
の結果は -2
になります。一方で、5
としたほうがわかりやすいと感じる人もいるでしょう。このように、どう感じるかは人それぞれです。
他のプログラミング言語では、負の数での余りの扱いが異なることもあります。例えば -17 % 4
とした際、3
と計算する場合もあります。これが自然だと感じる人も多いでしょう。
最終的には、プログラミング言語がどのように処理するか、またそれをどう理解するかが重要ですね。どちらの方が自然に感じるかは人それぞれで、理解しやすい方を選ぶのが良いでしょう。 自然に考えるとマイナス1が返ってこないというイメージが現れているのだと思いますが、意外とこのように整数でしか考えていないこともありますね。特に自分の場合、負の数の場合を見落としてしまったりするので、このケースが抜けがちです。これは非常に怖いことで、ここで勉強しているわけです。
C言語の話になりますが、特にC99(Cの標準規格のバージョン)では、これに関する仕様が決まっています。整数同士の除算の場合、結果の符号や余りについての仕様が厳密に定められています。Swiftでも同様に、符号付きの余りを考慮することが大切ですね。
例えば、負の数を正の数で割った時にどうなるかを調べてみると、Swiftでは「余り(%)演算子は左ハンドサイドの符号を採用する」という仕様になっています。つまり、左側のオペランドの符号に合わせた余りの値が返されるわけです。C99でも同じ結果が得られるので、Swiftの動作も正しいと言えます。
具体例を挙げると、Swiftでの-5 % 3
の結果は-2
になります。このように符号が揃えられた余りが得られるのは仕様です。したがって、例えば余りが5ではなくてマイナス2になることを期待する場合、その仕様は満たされないことになります。
この仕様を踏まえて、isMultiple(of:)
関数も適切に判定を行うようになっています。例えば、Numericプロトコルに準拠した型では、絶対値を取って演算するという形になっているのです。これにより、負の数にも対応できるようになっています。実装を見た限りでは、このように倍数であるかの判定が正しく行われるようになっているのです。
さらに、SignedIntegerプロトコルの場合には、絶対値を取らずに剰余(モジュロ)を計算して結果を判定するという方法が取られています。これは数学的な知識が必要となる部分であり、自分の理解が追いつかないかもしれませんが、非常に興味深い点です。
数学的な観点から見た剰余の話や、プログラムの世界(情報の世界)で見た場合の剰余の扱いについて、今後も深掘りしていきたいと思います。今日は時間になりましたので、ここまでにしておきます。ご参加いただき、ありがとうございました。