【スポンサーリンク】

「サイトで重大なエラーが発生しました」(ゼロ除算の2つの結果)

「サイトで重大なエラーが発生しました」(ゼロ除算の2つの結果)
  • PHPのバージョンを7.4から8.0に上げたら、カスタムプラグインがエラーになるようになりました。
  • エラーをみると「ゼロ除算(DivisionByZeroError)」。
  • これまでは除算後に NaN のチェックをしていたのですが、除算前に 0 のチェックが必要になったみたいです。
  • どうも、除算演算子で fdiv でなく intdiv が使われるようになっていたのが原因ようです。
\記事が役に立ったらシェアしてね/
【スポンサーリンク】

1. カスタムプラグインのエラー

PHPのバージョンを7.4から8.0に上げたら、以前に自分で作ったWordPressのカスタムプラグイン1がエラーになりました。

カスタムプラグインのエラー

エラーの詳細がメールで届いていました。

こんにちは。

WordPress には、サイトでプラグインやテーマが致命的なエラーを発生させた場合にそれを検知してこの自動メールでお知らせする機能があります。

今回の場合、WordPress がプラグイン ちいラボ統計 でエラーを捉えました。

エラー詳細

エラータイプ E_ERROR が /〜/chiilabo-stats-main.php ファイルの 498 行目で発生しました。
エラーメッセージ: Uncaught DivisionByZeroError:
Division by zero in /〜/chiilabo-stats-main.php:498

「DivisionByZeroError」が発生しているようです。

1-1. ゼロ除算のエラーが発生している

該当するスクリプトを見てみます。

ゼロ除算のエラーが発生している
$log = $post_id2log[$post->ID];

$pv_ave = ($log->pv / ceil($days[$post->ID]));
if (is_nan($pv_ave)) {
	$pv_ave = 0;
}

この $log->pv / ceil($days[$post->ID]) でゼロ除算のエラーになっているようです。

1-2. 除算の前に除数をチェック

ということで、事前に除数が 0 かどうかチェックするように修正しました。

$log = $post_id2log[$post->ID];

$days_value = ceil($days[$post->ID]);
if ($days_value == 0) {
	$days_value = 0;    
}

$pv_ave = ($log->pv / $days_value);

これでちゃんと動くようになりました。

2. NaNじゃなかったの?

NaNじゃなかったの?

逆になんで今まで動いていたんだろう……・

これまでも一応、ゼロ除算は考慮していたつもりでした。
ゼロで割った結果は NaNになっていたように思い、次の is_nan関数でチェックしていました。

$log = $post_id2log[$post->ID];

$pv_ave = ($log->pv / ceil($days[$post->ID]));
if (is_nan($pv_ave)) {
	$pv_ave = 0;
}

つまり、未定義の値になったら 0になるように修正していました。

しかし、PHPには、ゼロ除算の例外 DivisionByZeroError があります。
例外処理をしないと、処理がエラーになってしまいます。

NaN

NaN」とは、「Not a Number」の略で、「数値ではない」という意味です。
「計算できない」や「数値にならない結果」を示す特別な値です。

たとえば、0で割ったり、負の数の平方根を計算しようとした場合などにNaNが返されます。

2-1. 2種類の除算(fdiv, intdiv)

2種類の除算(fdiv, intdiv)

特別な値が返ってくるか、それとも例外になるかって、大違いじゃない。

これはややこしくて、PHPには2種類の除算用の関数があります。

浮動小数点数の割り算では、0.0での除算は NaN と定義されています。

var_dump(fdiv(0.0, 0.0)); 
// float(NAN)

一方、整数の割り算では、0での除算は DivisionByZeroError の例外処理になっています。

var_dump(intdiv(1, 0));
// Fatal error: Uncaught DivisionByZeroError: Division by zero in %s

3. 演算子では fdivとintdivが自動で切り替わる

除算の演算子( num1/num2 )を使った割り算では、
基本は小数の結果になります。
つまり、 fdiv が適用されています。

しかし、たまに intdiv が適用されることがあります。
intdiv が適用される条件は、

  • 割る数・割られる数が整数
  • 結果が割り切れる場合

除算演算子 (“/”) の返す値は浮動小数点数となります。
ただし、ふたつのオペランドがともに整数 (あるいは整数に変換できる文字列) であり、かつ結果が割り切れる場合には整数値を返します。
整数の除算については intdiv() を参照ください。

PHP: 算術演算子 – Manual

これは、割り切れる結果を「整数値」で返すためです。

3-1. ゼロ除算は割り切れるのか?

では、「ゼロ除算はどうなるの?」という疑問が生まれます。
「結果が割り切れる」の解釈が問題になってくるのです。

どうも、これまではゼロ除算は「結果が割り切れない」という扱いで、fdivが適用されNaNになっていたように思います。
ところが、PHP8になってふたつのオペランドがともに整数なら、ゼロ除算でも intdivの方が適用されているようなのです2

ゼロ除算は割り切れるのか?

それでこれまではエラーになっていなかったんだね。

こちらもどうぞ。
[WordPress]記事ごとの平均PVを集計するサブメニューを自作プラグインに追加した
[WordPress]記事ごとの平均PVを集計するサブメニューを自作プラグインに追加した
どんな記事が安定して読まれているのか把握するために、平均PVを調べたいと思いました。前回作った月別ページビュー集計の自作プラグインに追加します。 前回はこちら。 管理ページにサブメニューを追加する(add_submenu_page) 最終的に出来上がったのがこちら。 ブログの勢いを将棋の駒でランク付けしています。 書いた記事が、駒得で変換されるのでモチベーションが上がります。 野球が好きなら、ヒットやホームランでもいいんだろうね。 まずは、メニューに項目を追加します。Word...

[WordPress] 投稿月でグループ分けした月別PV集計表を見るためのカスタムプラグインを作った【ChatGPTと】
[WordPress] 投稿月でグループ分けした月別PV集計表を見るためのカスタムプラグインを作った【ChatGPTと】
一ヶ月分のブログ公開がどれぐらいのページビューにつながっているのか、集計する自分用のWordPressプラグインを作成しました。 自分にとっては未経験の分野でしたが、対話型AI「ChatGPT」に相談してみると、使える叩き台を用意してくれました。 WordPressプラグインづくりははじめてでしたが、かなりの時間短縮。無事に完成しました。 アクセス集計プラグイン 一ヶ月分のブログ公開が、どれぐらいの成果になっているのか知りたいことがあります。 これまでは、Google Ana...

WordPressカスタムプラグインのタイムアウトを避ける(mixhost)
WordPressカスタムプラグインのタイムアウトを避ける(mixhost)
カスタムプラグインでサイトの統計情報を分析しているのですが、時々タイムアウトで動かなくなってしまうんです。 そこで、cPanelのMultiPHP INIエディタを使って、max_execution_timeの設定を変更してみました。 これで、プラグインが途中で止まらずに済むようになりました。 カスタムプラグインの動作が安定しない カスタムプラグインでサイト統計情報を分析しています。 ところが、最近 そのプラグインの統計ページが動かないときがあります。ページの再読み込みすると...

(補足)

  1. [WordPress]記事ごとの平均PVを集計するサブメニューを自作プラグインに追加した – スマホ教室ちいラボ
  2. 処理系にもよるかも。
QRコードを読み込むと、関連記事を確認できます。

「サイトで重大なエラーが発生しました」(ゼロ除算の2つの結果)
【スポンサーリンク】
タイトルとURLをコピーしました