プログラミングで四則演算をする時に、割り算(除算)をする時に0を任意の数値で割る事は問題ないのだが、任意の数字 を0で割ってはいけないという数学的ルールがそれぞれの言語にも適用されるので、エラーを出さない様なプログラムをコーディングする必要があります。
当たり前のことだが中々意識してプログラムをする事がなかったので、調査を含めて、自分のコーディング規則を作成しておきます。
何故0で割ってはいけないかという理由がTED(Youtube)で説明されているので、知りたい人は見て見てください。
(英語です)
VIDEO
割り算についての調査
除法(割り算)のwikipedia
割り算は「除法」や「除算」が学術的な呼び名で、四則演算の二項演算のひとつとされます。
割り算の公式とそれぞれの名称は以下ようになっているので、覚えておくと説明する際などに便利でしょう。
被除数 ÷ 除数 = 商 ... 剰余
プログラム言語別0で割った時の挙動チェック
PHP
echo 10 / 5;
echo PHP_EOL;
echo 0 / 2;
echo PHP_EOL;
echo 10 / 0;
echo PHP_EOL;
$ php 0.php
> 2
> 0
> Warning: Division by zero in /Users/yugeta/web/labo/0devide/0.php on line 9
> INF
「Warning: Division by zero」というwarningが出て「INF」というInfinityエラーが発生してしまいます。
「Infinity」は無限大という事で、プログラム内で無限ループが発生してしまう不具合なんですね。
Javascript
console.log( 10 / 5 );
console.log( 0 / 2 );
console.log( 10 / 0 );
> 2
> 0
> Infinity
きちんと「Infinity」と表示されてしまってます。
このままグラフなどに数値代入しようとすると、そこでエラーになる事がわかります。
Ruby
puts 10 / 5
puts 0 / 5
puts 10 / 0
> 2
> 0
> 0.rb:4:in `/': divided by 0 (ZeroDivisionError)
from 0.rb:4:in `<main>'
「ZeroDivisionError」としっかり怒られます。
やはりこのまま使うと想定しない不具合に繋がりますね。
Python
#coding: UTF-8
print 10 / 5
print 0 / 5
print 10 / 0
> 2
> 0
> Traceback (most recent call last):
File "0.py", line 5, in <module>
print 10 / 0
Pythonは、HTMLタグでエラーを返すんですね。
知らんかった。
そして、やはり長めのエラー文言でしっかり怒られるので、これも不具合まっしぐらでしょう。
Shell
#!/bin/bash
echo $((10/5))
echo $((0/5))
echo $((10/0))
echo `expr 10 / 0`
$ sh 0.sh
> 2
> 0
> 0.sh: line 5: 10/0: division by 0 (error token is "0")
> expr: division by zero
「Infinity」と怒られないですが、「division by 0」として怒られます。
また、exprで計算した場合もきちんと叱ってくれます。
Golang
package main
import "fmt"
func main(){
fmt.Println(10 / 5)
fmt.Println(0 / 5)
fmt.Println(10 / 0)
}
$ go run 0.go
> 2
> 0
--
## 0で割った場合は、描きエラーで実行停止されます。
# command-line-arguments
./0.go:8: division by zero
Goは0で割る式があると、その場でプログラムが停止します。
途中まで実行もされずに、コンパイルエラーになるようです。
おそろしや・・・
どういうケースで発生しやすいのか・・・
0で割るケースってどういう時に発生するのでしょうか?
割り算を使うケースは、データの割合を出す場合に使うケースが圧倒的に多いので、レポーティングシステムなどで発生しがちです。
ECサイトなどで、複数商品ある売上の商品単価の平均を出したい場合、商品がまだ登録されていなければ、0で割ってしまう場面に遭遇します。
また、ユーザー登録するサービスなどで、ユーザー平均指標を出したい場合に、ユーザー登録が0人の場合も、0で割ってしまう事になります。
それらを防ぐために、0人の場合は、WEBページで事前にエラーを表示して、計算式まで辿り着けなくさせる対策を行ったり、0で割った場合の答えを0にしてしまう事で対応するのが一般的だと考えられます。
除数「0(ゼロ)」を考慮した記述
PHP
<?php
$a = 10;
$b = 0;
echo (!$b) ? 0 : $a / $b;
echo PHP_EOL;
三項演算子を使って、結果を「0」として出力すると、不具合が発生しにくいプログラムになるでしょう。
JavaScript
var a = 10;
var b = 0
console.log((!b) ? 0 : a/b);
JSも基本的には三項演算子でかるくクリアできます。
Ruby
a = 10
b = 0
puts (b == 0) ? 0 : a / b
> 0
rubyも普通に三項演算子で対応できます。
Python
a = 10
b = 0
print 0 if b == 0 else a / b
> 0
Pythonの三項演算子は、通常の書き方と違うので要注意です。
これって普通にif文じゃんって思ったのは僕だけ?
Shell
#!/bin/bash
a=10
b=0
if [[ $b -eq 0 ]]; then
echo 0
else
echo $(($a / $b))
fi
shellはif文でないと安定して使えないですね。
Golang
package main
import "fmt"
func main(){
a := 10
b := 0
if a == 0 || b == 0 {
fmt.Println(0)
} else{
fmt.Println( a / b )
}
}
Go言語は三項演算子が無いので、if文できちんと書きます。
Go言語のif文で注意すべきポイントは、elseの書き方が"} else {"と繋げて書かないとエラーになります。
間に改行を挟むとエラーになるので、最初はかなりハマってしまいましたが、非常に繊細な言語だと改めて感じました。
0 件のコメント:
コメントを投稿