bigdecimal icon indicating copy to clipboard operation
bigdecimal copied to clipboard

BigMath methods returns inaccurate value for rational

Open tompng opened this issue 2 months ago • 1 comments

Because Rational is simply converted to BigDecimal with the given precision. Precision is not that simple. Though it may not be a responsibility for BigMath.

BigMath.exp: Maximum 19 digits precision loss

BigMath.exp(10**19/3r, 50).to_s[0,52]
#=> "0.31897971307307432918427098497346266668405585204999"
BigMath.exp(10**19/3r, 1000).to_s[0,52]
#=> "0.31897971307307432918427098497347329934115828786096"

BigMath.log: Many precision loss near x=1

BigMath.log(1+1r/12345**9, 50)
#=> 0.15016895257719999999999999999999999998872464284093e-36
BigMath.log(1+1r/12345**9, 1000).mult(1, 50)
#=> 0.1501689525772244244950394251097065861542145195459e-36

BigMath.sin: Many precision loss near x=n*π

x = (31415926535897932384626433832795 * 7 + 1).quo(7 * 10**40)
BigMath.sin(x, 50)
#=> 0.26542232205820974944592307816406286208998628034825e-40
BigMath.sin(x, 1000).mult(1, 50)
#=> 0.26542232248678117801735164959263429066141485177682e-40

Each method requires different Rational to BigDecimal conversion. For example:

  • log: x < 1/2r ? BigDecimal(x, prec) : BigDecimal(x - 1, prec) + 1
  • exp: BigDecimal(x, prec + [BigDecimal(x, 1).exponent, 0].max)
  • sqrt: Nothing special. BigDecimal(x, prec)
  • sin, cos: Needs precision increasing loop

tompng avatar Oct 11 '25 20:10 tompng