1

したがって、理論的には、Ruby には整数の最大値はなく、必要なだけ大きくすることができると読みました。ただし、以下を乗算すると、負の値になります (これはオーバーフローの兆候だと思いますか?):

44404051714 * 44404051714 => -2081807267335685116

誰かが私にこれを説明できますか?

4

1 に答える 1

3

これは、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 プログラムではオーバーフローが発生しないと想定することでこれを利用でき、そのロジックに基づいてオーバーフロー チェックを最適化できます。ba * bc / a != b

そのため、お使いのバージョンの Ruby がかなり最近のコンパイラでコンパイルされている場合 (最近のバージョンの Clang が良い例です)、それが原因である可能性があります。

いずれにせよ、これはバグ レポートの価値があると思います。これが原因でなくても、上記の C コードは疑わしいものです。


volatile long c編集: Daniel Fischer は、宣言があることをコメントで指摘しています。理論的には、これによりオーバーフロー チェックが最適化されないようにする必要があります。それが問題の原因である場合、これは Ruby のコードのバグではなく、コンパイラのバグになります。

于 2012-11-06T20:54:17.183 に答える