したがって、理論的には、Ruby には整数の最大値はなく、必要なだけ大きくすることができると読みました。ただし、以下を乗算すると、負の値になります (これはオーバーフローの兆候だと思いますか?):
44404051714 * 44404051714 => -2081807267335685116
誰かが私にこれを説明できますか?
したがって、理論的には、Ruby には整数の最大値はなく、必要なだけ大きくすることができると読みました。ただし、以下を乗算すると、負の値になります (これはオーバーフローの兆候だと思いますか?):
44404051714 * 44404051714 => -2081807267335685116
誰かが私にこれを説明できますか?
これは、Ruby のFixnum
クラスの乗算の実装におけるバグのようです。ソースを見ると、 numeric.cfixmul
の関数からの次の行 (大幅に省略されています)が疑わしいものとして飛び出します。
...
2645: long a, b;
...
2663: c = a * b;
2664: r = LONG2FIX(c);
...
2667: if (FIX2LONG(r) != c || c/a != b) {
2668: r = rb_big_mul(rb_int2big(a), rb_int2big(b));
...
私が正しく読んでいれば、それはFixnum
乗算を行っているコードと、結果を実際に として再計算する必要があるかどうかを判断するためにオーバーフロー検出を行っているはずのコードのビットからのものBignum
です。問題は、それが悪い C コードであることです: 型が long でありa
、C 標準に従って未定義の動作を生成するオーバーフローの場合。優れたコンパイラは、正しい C プログラムではオーバーフローが発生しないと想定することでこれを利用でき、そのロジックに基づいてオーバーフロー チェックを最適化できます。b
a * b
c / a != b
そのため、お使いのバージョンの Ruby がかなり最近のコンパイラでコンパイルされている場合 (最近のバージョンの Clang が良い例です)、それが原因である可能性があります。
いずれにせよ、これはバグ レポートの価値があると思います。これが原因でなくても、上記の C コードは疑わしいものです。
volatile long c
編集: Daniel Fischer は、宣言があることをコメントで指摘しています。理論的には、これによりオーバーフロー チェックが最適化されないようにする必要があります。それが問題の原因である場合、これは Ruby のコードのバグではなく、コンパイラのバグになります。