Skip to content

Commit c804b09

Browse files
committed
Use BigDecimal("1e#{n}") instead of ten**n to make calculation faster
1 parent 73825c8 commit c804b09

File tree

2 files changed

+6
-7
lines changed

2 files changed

+6
-7
lines changed

lib/bigdecimal.rb

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,19 @@ def sqrt(prec)
2020
raise FloatDomainError, 'sqrt of negative value' if self < 0
2121
raise FloatDomainError, "sqrt of 'NaN'(Not a Number)" if nan?
2222

23-
ten = BigDecimal(10)
2423
n_digits = n_significant_digits
2524
prec = [prec, n_digits].max
2625

2726
if n_digits < prec / 2
2827
# Fast path for sqrt(16e100) => 4e50
29-
base = ten ** ((n_digits + 1) / 2 - exponent / 2)
30-
n = self * base * base
28+
ex = (n_digits + 1) / 2 - exponent / 2
29+
n = (self * BigDecimal("1e#{2 * ex}")).to_i
3130
sqrt = Integer.sqrt(n)
32-
return BigDecimal(sqrt).div(base, prec) if sqrt * sqrt == n
31+
return BigDecimal(sqrt) * BigDecimal("1e#{-ex}") if sqrt * sqrt == n
3332
end
3433

3534
ex = prec + BigDecimal.double_fig - exponent / 2
36-
base = ten ** ex
37-
sqrt = Integer.sqrt(self * base * base)
38-
BigDecimal(sqrt).div(base, prec + BigDecimal.double_fig)
35+
sqrt = Integer.sqrt(self * BigDecimal("1e#{2 * ex}"))
36+
BigDecimal(sqrt) * BigDecimal("1e#{-ex}")
3937
end
4038
end

test/bigdecimal/test_bigdecimal.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,6 +1186,7 @@ def test_sqrt_bigdecimal
11861186
assert_equal(BigDecimal('11.1'), BigDecimal('123.21').sqrt(100))
11871187
assert_equal(BigDecimal('11e20'), BigDecimal('121e40').sqrt(100))
11881188
assert_in_epsilon(Math.sqrt(121e41), BigDecimal('121e41').sqrt(100))
1189+
assert_in_epsilon(Math.sqrt(2e100), BigDecimal('2e100').sqrt(10))
11891190
end
11901191

11911192
def test_sqrt_5266

0 commit comments

Comments
 (0)