🕌
[Feature #21650] 巨大な数値の場合に Rational#floor(ndigits) が遅くなっているバグ報告
[Feature #21650] Performance regression: Rational#floor(ndigits) extremely slow for huge ndigits in Ruby 3.4 (ok in 3.2)
- Ruby 3.2 と比較して Ruby 3.4 で巨大な数値の場合に
Rational#floor(ndigits)が遅くなっているというバグ報告- 手元で試してみたら Ruby 3.3 -> 3.4 で遅くなっているみたい
require "benchmark"
puts RUBY_DESCRIPTION
t = Benchmark.realtime { (2 ** -3).floor(2 ** 31) }
puts "elapsed: #{t.round(3)}s"
# Ruby 3.2 => elapsed: 0.0s
# Ruby 3.3 => elapsed: 0.0s
# Ruby 3.4 => elapsed: 47.018s
- これなんですが Ruby 3.3 までは
#**の場合に巨大な値な場合にはInfinityを返していたんですが Ruby 3.4 からより厳密に計算するようになったのでその影響を受けているみたいですね - 例えば次のようなコードが Ruby 3.3 では意図しないが Ruby 3.4 では意図する挙動になる
# returns Rational(1, 10**(2**n))
def calc(n)
d = 10
n.times { d *= d }
Rational(1, d)
end
p calc(1) #=> (1/100)
p calc(2) #=> (1/10000)
p calc(3) #=> (1/100000000)
# この2つは期待する挙動
p calc(10).floor(2**10 - 1) == 0 # => true
p calc(20).floor(2**20 - 1) == 0 # => true
# これも true になってほしいが Ruby 3.3 だと false になる
p calc(30).floor(2**30 - 1) == 0
# => false
# => true
- 現状では問題のコードはテストで利用していただけで何かしら課題があるわけではないみたい
Discussion