Skip to content

Commit f718178

Browse files
authored
Fix precision of x.power(y, prec) when the result is nearly infinity (#439)
1 parent a267ca7 commit f718178

File tree

2 files changed

+23
-0
lines changed

2 files changed

+23
-0
lines changed

lib/bigdecimal.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,13 @@ def power(y, prec = nil)
182182
end
183183
ans.mult(1, prec)
184184
else
185+
if x > 1
186+
# To calculate exp(z, prec), z needs prec+max(z.exponent, 0) precision if z > 0.
187+
# Estimate (y*log(x)).exponent
188+
logx_exponent = x < 2 ? (x - 1).exponent : Math.log10(x.exponent).round
189+
ylogx_exponent = y.exponent + logx_exponent
190+
prec2 += [ylogx_exponent, 0].max
191+
end
185192
BigMath.exp(BigMath.log(x, prec2).mult(y, prec2), prec)
186193
end
187194
end

test/bigdecimal/test_bigdecimal.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,6 +1996,22 @@ def test_power_with_huge_value
19961996
assert_equal(BigMath.exp(1, 100), (1 + BigDecimal(1).div(n, 120)).power(n, 100))
19971997
end
19981998

1999+
def test_power_almost_infinite
2000+
omit if EXPONENT_MAX < 9e+18
2001+
2002+
x = BigDecimal(1.9)
2003+
y = BigDecimal('1e+18') + 0.1
2004+
assert_equal(x.power(y, 120).mult(1, 100), x.power(y, 100))
2005+
2006+
x = BigDecimal("9e+#{10**17}").div(7, 100)
2007+
y = BigDecimal(1.9)
2008+
assert_equal(x.power(y, 120).mult(1, 100), x.power(y, 100))
2009+
2010+
x = BigDecimal("9e+#{10**9}").div(7, 100)
2011+
y = BigDecimal('1e+8') + 0.1
2012+
assert_equal(x.power(y, 120).mult(1, 100), x.power(y, 100))
2013+
end
2014+
19992015
def test_power_precision
20002016
x = BigDecimal("1.41421356237309504880168872420969807856967187537695")
20012017
y = BigDecimal("3.14159265358979323846264338327950288419716939937511")

0 commit comments

Comments
 (0)