Wikipedia:井戸端/subj/expr関数の演算子「mod」の桁数制限

数式の演算について[編集]

私が何か勘違いしているのかもしれませんが、Help:条件文expr関数についてお伺いします。

演算子「mod」は、除法の余りを求めるもので、
{{#expr: 10 mod 7}}=3(10÷7=1…3)、{{#expr: 11 mod 3}}=2(11÷3=3…2)、{{#expr: 25 mod 10}}=5(25÷10=2…5)
となるのですが、数が大きくなると、
{{#expr: 12345678912345673 mod 10}}=2
といったように、答えが変になってしまう場合があります。

数字の大きさに制限があるのでしょうか?--Kazukiokumura(奥村和生) 2008年7月27日 (日) 10:28 (UTC)[返信]

桁あふれによるものではないでしょうか?MediaWikiのソースコードとか見たことないので詳しいことは分かりませんが、PHPでは確かサーバの環境によって扱える数の上限が決まっているはずです。--青子守歌会話/履歴 2008年7月27日 (日) 10:52 (UTC)[返信]
Help:条件文に「内部の実装は IEEE 754倍精度小数です」とあり、「12345678912345673」が倍精度少数で表現できる精度を超えてしまっているのではないかと思います。コンピューターの少数表現をきちんと勉強していないので確信はないのですが、「12345678912345673」は2進数で54桁であり、倍精度少数で表現できる自然数は2進数で(最後の0の並びはカウントせずに)53桁までだと理解しています。--Mizusumashi(みずすまし) 2008年7月28日 (月) 13:20 (UTC)--追記:2008年7月28日 (月) 13:38 (UTC)[返信]
そうなんですか。わざわざ私の疑問に答えていただき、どうもありがとうございました。--Kazukiokumura(奥村和生) 2008年7月30日 (水) 10:35 (UTC)[返信]
「12345678912345673」を2進数で表すと54桁の「101011110111000101010001011110000101001101011001001001」になります。IEEE 754の倍精度小数では実数部が52桁なので、このうち上から52桁までが有効であり、下2桁は丸められます。10進数としては「12345678912345672」の次に取れる値は「12345678912345676」になり「12345678912345673」はこの2つの数の近いほうに丸められます。つまり、「12345678912345673 mod 10」は「12345678912345672 mod 10」を計算することになり、結果は2になります。--アルビレオ 2008年8月1日 (金) 10:02 (UTC)[返信]
自分の理解にそう自信があるわけではないのですが・・・
「IEEE 754の倍精度小数では実数部が52桁なので、このうち上から52桁までが有効」との点は、「IEEE 754の倍精度小数では仮数部が52桁なので、このうち上から53桁までが有効」というのが正しいのではないかと思います。
というのは、仮数部は正規化すると「1.・・・」という形になるので(「10.01」は「1.001」に、「0.00111」は「1.11」に正規化され、いずれも「0.1001」や「0.111」に正規化されない -「0」だけ例外-)、最上位桁がほぼ必ず「1」になり、そのため最上位桁の「1」は無視して保存されるようです。
浮動小数点数にも「仮数部に割り当てられたビット数をnとすると、2進数での有効桁数はn+1となる」と書かれています。(倍精度には「指数部が全て 0 でない限り、この形式では「暗黙の整数ビット」を 1 とみなす。従って小数部の52ビットだけがメモリフォーマット上に出現し、全体としての精度は52ビット(十進に直すと15桁)である」と書かれていますが、これの後半はおそらく、この編集で埋め込まれた誤りではないかと思います。)--Mizusumashi(みずすまし) 2008年8月1日 (金) 11:26 (UTC)[返信]
私の前回の記述については、Mizusumashiさんの指摘が正しいです。よく見直さずに投稿してしまい、失礼しました。
なお、確かに仮数部が52ビットなので、2進数での有効桁数は53桁なのですが、精度としては先頭の1ビットが常に1になることから52ビットで正しいと思います。仮数部が全て1の場合10進数としては「9007199254740991」になります。つまり「9007199254740992」になると桁あふれして、「9007199254740993」と区別できなくなります。
Windowsの電卓も内部は同様の実装になっているようで、「9007199254740991」は2進数に変換したときにDwordに入りますが、「9007199254740992」を2進数に変換するとQwordでないと扱えなくなります。
10進16桁で桁落ちすることがあるので、精度は15桁で正しいはずです。--アルビレオ 2008年8月2日 (土) 10:30 (UTC)[返信]
たしかに、「精度としては先頭の1ビットが常に1になることから52ビットで正しい」ようにも思います。このあたりの言い回しは、私はよく分かっておらず、ちょっと判断が付きかねます(ごめんなさい)。また、「10進16桁で桁落ちすることがあるので、精度は15桁」とのいうのも、正しいように思います。
そうすると、『倍精度には「指数部が全て 0 でない限り、この形式では「暗黙の整数ビット」を 1 とみなす。従って小数部の52ビットだけがメモリフォーマット上に出現し、全体としての精度は52ビット(十進に直すと15桁)である」と書かれていますが、これの後半はおそらく、この編集で埋め込まれた誤りではないかと思います。』との私の記述は誤りだったかもしれません。--Mizusumashi(みずすまし) 2008年8月2日 (土) 19:00 (UTC)[返信]