質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.61%

  • PHP

    19914questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

何故、商が少数で余りが負数になるのか

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 322

aaaaaaaa

score 465

PHP_INT_MAXぼ値を超えた数値を割ると商が少数に余りが負数になります。負の余りなんてあったっけと思いつつ調べると、定義次第とありました。
例えば、3486784400 % 7は、498112057(商)...1(余り)ですが、PHPで計算すると498112057.57143(商)...-3(余り)となります。

なぜ、商が少数となり余りが負数になるのでしょうか。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • m6u

    2018/05/15 19:44 編集

    《商が少数で余りが負数になる》事例の再現方法、実行環境を示してください。32bit環境なのか64bit環境なのかも添えて。

    キャンセル

回答 4

checkベストアンサー

+7

PHPの/は左辺と右辺が整数(int)で、かつ、割りきれる場合のみ整数(int)を返し、それ以外は浮動小数点数(float)を返します。整数商を求めたい場合はintdiv()を使用してください。しかし、3486784400 % 7-3になる環境ではintdiv(3486784400, 7)はエラーになるでしょう。それを含めて、3486784400 % 7がなぜ-3になるのかを説明します。

 3486784400 を 7 で割った余りは -3 ?

この演算結果は算術的には全く正しくありません。確かに定義によって剰余が負の数になる場合がありますが、それは左辺と右辺の少なくとも一方が負の数になる場合のみです。両辺が正の数の場合は必ず正の数になります。勝手に負の数になることはありませんし、そのような定義もされることはありません。

なんだ、PHPは算数も出来ないのか!とお思いでしょうが、違います。正確には、PHPはある数より大きい整数については算数が出来ない、です。このとある数はPHP_INT_MAXという定数で取得でき、OSやアーキテクチャによって固定で、通常は2147483647(32bit環境)か9223372036854775807(64bit環境)のどちらかです。

気付きましたか?34867844002147483647より大きい整数です。そのため、PHP_INT_MAX2147483647である環境では3486784400を整数として扱えません。そのため、整数の簡単な算数ですら、PHPは正確に出来ないのです。

では、実際どのような処理の結果-3というとんちんかんな答えを出してしまったのかを見ていきましょう。下記処理はPHP_INT_MAX2147483647の場合です。9223372036854775807では正しく1と答えてくれるので、該当しないことに注意してください。

まず、3486784400というリテラル表記ですが、整数(int)ではありませんPHP_INT_MAXを越えているため、PHPではこの表記の数を整数として扱えないからです。実際には何になるのかというと、var_dump()で確認できます。

var_dump(3486784400);
// => float(3486784400)

そう、浮動小数点数(float)です。intdiv(3486784400, 7)がエラーになるのは、整数しか受け付けないintdiv()に浮動小数点数(float)を入れてしまったからです。そして、困ったことにPHPでの%の剰余計算も整数(int)同士の演算しか考慮していません。%はエラーにならない代わりに、左辺と右辺について「整数(int)に変換する」という処理をします。7は既に整数(int)ですので変換は起きませんが、3486784400は浮動小数点数(float)なので、整数(int)への変換が発生します。実際、整数(int)へ変換しようとするとどうなるのでしょうか?

var_dump((int)(3486784400));
// => int(-808182896)

謎の整数-808182896が出てきました。このようなPHP_INT_MAXを越えている場合どのような値になるかについて、PHPマニュアルでは結果は未定義とされています。未定義だから何でもあり、では面白くないので、ソースコードを追いかけてみましょう。整数(int)変換は途中色々あるのですが、範囲超えている浮動小数点数(float)の整数(int)への変換は最終的にzend_dval_to_lval_slow()で行われます。

ソースコード: Zend/zend_operators.c 3102行目 zend_dval_to_lval_slow()の定義(32bit) - PHP 7.2.6

やっていることは、2の32乗(4294967296)の剰余を求めて、符号無し整数(zend_ulong)にした後、符号有り整数(zend_long)、つまり、整数(int)にキャストしています(CのdoubleがPHPのfloat、Cのzend_longがPHPのintに対応し、zend_ulongはPHP上にはあらわれない)。

3486784400に対する4294967296の剰余は3486784400です。32bitの符号無し整数ではこれは表現可能ですので、このままの整数値になります。これを32bitの符号あり整数にキャストするわけですが、32bitの2の補数表現の環境では、4294967296を引いた数、つまり、-808182896になります。ただし、これらは環境依存であるため、全ての環境で同じような動作をするとは限らない事に注意してください。ここら辺はCをちょっと囓らないと難しいかも知れません。

とりあえず、環境によりますが、-808182896になることはわかりました。あとは-808182896 % 7が何になるかです。PHPの剰余の結果は左辺の符号と同じ符号で絶対値が右辺より小さくなるように求めるとなっていますので、答えは-3となるわけです。

※ 左辺が負の数の時に右辺も負の数になるかどうかは言語によって異なります。剰余演算 - Wikipediaに各言語の結果一覧がありますので、参考にしてみてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

なんか、WindowsじゃなくてLinux使えって事らしいですねー。

整数

整数のサイズはプラットフォームに依存しますが、 約 20 億 (32 ビット符号付) が一般的な値です。 64 ビットプラットフォームでの通常の最大値は、およそ 9*10^18 (900京) になります。 

しかし PHP 7 より前のバージョンにおける Windows は例外で、Windows で PHP 7 より前のバージョンを使う場合はは常に 32 ビットとなります。 PHP は符号無し整数をサポートしていません。

整数のサイズは定数 PHP_INT_SIZE(※注:Byte数) で、 そして整数の最大値は定数 PHP_INT_MAX でそれぞれ決まります。 これらの定数は、PHP 5.0.5 以降で使えます。 PHP 7.0.0 以降では、整数の最小値を表す定数 PHP_INT_MIN が使えるようになりました。

うそつきー! Windows XAMPP  PHP7.2.3 でも PHP_INT_SIZE は 4 で PHP_INT_MAX は 2147483647 ぞ!

<?php
$val = 3486784400;
echo gettype($val) . "\n";    // ← 結果 double ウェウェウェ

追記

% (moduler) は左辺がINTEGERでないとダメなので double になった 3486784400 を int に暗黙キャストするんだけど、オーバーフローして値がマイナスになるんだろうな。

一方、商については double をそのまま割って型は double のまま。

<?php
$val = 3486784400;
echo gettype($val) . "\n";   // ← double
echo gettype($val % 7) . "\n"; // ← integer
echo gettype($val / 7) . "\n"; // ← double

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/15 20:16

    https://windows.php.net/download/
    で64bit版をダウンロードするしか!

    キャンセル

  • 2018/05/15 20:26

    あー、そだったね、WindowsのXAMPPって、いまだに32bit版だったんだっけ…。

    キャンセル

0

Online PHP editor | output for 0iat0

<?php

echo 3486784400 % 7 . PHP_EOL;
echo 3486784400 / 7 . PHP_EOL;


実行結果:
実行結果のスクリーンショット

質問文にあるような結果を導き出せないので、説明できません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

なぜ、商が少数となり

PHPには整数除算が無くて、/は実数の除算なので割り切れない場合に商が小数になるのは当然です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • PHP

    19914questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。