Closed ysakasin closed 3 years ago
加算ダイスに以下のように極端に大きな数が含まれると、桁数が合わない小さな値が出力される。
1D6*1504642339053716000000 (1D6*1) > 2[2]*1 > 2
JavaScriptで浮動小数点数と整数が区別されないというRubyとの差を吸収するために様々なところに #to_i を付加するパッチを当てているが、Opalの Number#to_i の挙動が指数表記されるような値に対して正確でない。
#to_i
Number#to_i
https://github.com/bcdice/bcdice-js/blob/83a66236aea1f5c7e2e95bc29b0f147dcb59982f/patch.diff#L51 https://github.com/bcdice/bcdice-js/blob/83a66236aea1f5c7e2e95bc29b0f147dcb59982f/patch.diff#L132
Number#to_i はparseInt() を用いている。parseInt() は入力を文字列化してから数値に変換するが、入力が指数表記されるような大きな値である場合、以下の注釈で指摘されているように正確に変換できない。
parseInt()
数値によっては e の文字を文字列表現の中で使用しますので (例えば 6.022e23 は 6.022 × 10^23 を表します)、parseInt を使用して数値を切り捨てると、とても大きな数字やとても小さな数字を使用する際に予期しない結果を生み出すことがあります。parseInt を Math.floor() の代用として使うべきではありません。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/parseInt#description
1.504642339053716e+21 は文字列に変換すると "1.504642339053716e+21" となるが、 parseInt() は指数記法を解釈できないため、小数点までを認識し 1 に変換される。
1.504642339053716e+21
"1.504642339053716e+21"
1
Rubyは整数からシームレスに多倍長整数に移行するが、JavaScriptおよびOpalではサポートされていないため、Rubyと全く同じ挙動にすることは事実上不可能である。よって、bcdice-jsでは指数表記されたまま扱うようにするのが最善だと思われる。
以下の2パターンを提案する
Math.trunc()
リリースがいつされるかわからないので、いつ頃改善できるか不明
Number#trancate
すぐ直せるが Number#truncate の処理が煩雑
Number#truncate
ココフォリアのDicsordサーバーにて報告された (該当メッセージ)
夜遅くに失礼します。不具合なのかどうかわかりませんが、これまでできていたE+までの計算ができなくなっています。もしアプデか何かによる仕様でしたら申し訳ありません。ご確認宜しくお願いします。 10d1038581232830342440000527268773697775500000150464233905371600000012056635259482012200d62d421d41d6661d3966 (10D1038581232830342440000527268773697775500000112056635259482012200D62D421D41D6661D3966) > 68[6,6,4,8,8,9,4,6,8,9]38581232830342440000527268773697775500000112056635259482012737[5,3,1,5,1,6,1,3,2,4,6,1,5,5,6,1,5,1,5,1,4,5,5,5,3,5,2,1,3,2,5,1,4,5,1,1,6,5,1,6,2,5,6,6,4,4,5,5,5,1,3,5,3,2,5,3,6,1,1,6,3,4,4,2,1,6,5,6,3,2,3,2,6,4,3,4,5,1,6,6,5,5,5,6,6,6,2,5,4,5,1,5,6,3,5,3,5,3,3,6,5,4,1,5,1,2,1,6,1,2,3,6,6,3,4,6,6,1,5,3,4,6,3,5,5,6,6,4,1,3,4,6,6,5,5,5,1,5,6,4,4,2,5,4,6,6,2,1,2,2,5,2,5,2,6,1,3,1,3,3,3,6,5,5,6,3,5,2,4,3,2,2,2,3,3,4,3,3,1,5,1,3,2,5,2,2,2,4,3,3,1,2,3,6,3,5,2,6,1,5]6[4,2]22[2]636[636]12[12]*66 > 792 現状出目が極端に大きいダイスを振るとこのようになってしまいます。
ひとまずOpal側の修正が必要ということで。
問題の概要
加算ダイスに以下のように極端に大きな数が含まれると、桁数が合わない小さな値が出力される。
原因
JavaScriptで浮動小数点数と整数が区別されないというRubyとの差を吸収するために様々なところに
#to_i
を付加するパッチを当てているが、OpalのNumber#to_i
の挙動が指数表記されるような値に対して正確でない。https://github.com/bcdice/bcdice-js/blob/83a66236aea1f5c7e2e95bc29b0f147dcb59982f/patch.diff#L51 https://github.com/bcdice/bcdice-js/blob/83a66236aea1f5c7e2e95bc29b0f147dcb59982f/patch.diff#L132
Number#to_i
はparseInt()
を用いている。parseInt()
は入力を文字列化してから数値に変換するが、入力が指数表記されるような大きな値である場合、以下の注釈で指摘されているように正確に変換できない。https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/parseInt#description
1.504642339053716e+21
は文字列に変換すると"1.504642339053716e+21"
となるが、parseInt()
は指数記法を解釈できないため、小数点までを認識し1
に変換される。どのように扱うか
Rubyは整数からシームレスに多倍長整数に移行するが、JavaScriptおよびOpalではサポートされていないため、Rubyと全く同じ挙動にすることは事実上不可能である。よって、bcdice-jsでは指数表記されたまま扱うようにするのが最善だと思われる。
解決方法
以下の2パターンを提案する
1. Opalに対してPRを送る
Number#to_i
で指数記法が捨てられないようにPRを出すMath.trunc()
相当の処理に変更するリリースがいつされるかわからないので、いつ頃改善できるか不明
2. bcdice-jsで工夫することで解決する
Number#to_i
をNumber#trancate
で代用するすぐ直せるが
Number#truncate
の処理が煩雑決定したいこと
報告発生源
ココフォリアのDicsordサーバーにて報告された (該当メッセージ)
参考資料