bigdecimal icon indicating copy to clipboard operation
bigdecimal copied to clipboard

BigDecimal#round raises FloatDomainError regardless of exception mode

Open mrkn opened this issue 2 years ago • 2 comments

BigDecimal::INFINITY.round shouldn't cause FloatDomainError when BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY) == 0 but it raises the error.

$ ruby -rbigdecimal -e "BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false); BigDecimal::INFINITY.round"
-e:1:in `round': Computation results in 'Infinity' (FloatDomainError)
	from -e:1:in `<main>'

mrkn avatar Apr 20 '22 01:04 mrkn

  1. It happens only when precision is 0 (defailt), it works well when we define a non-zero precision:
> BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false); BigDecimal::INFINITY.round(1)
# => Infinity
  1. With precision=0, #round converts a decimal to an integer and it's according to the docs

If n is specified and negative, at least that many digits to the left of the decimal point will be 0 in the result, and return value will be an Integer. https://ruby-doc.org/stdlib-3.0.3/libdoc/bigdecimal/rdoc/BigDecimal.html#method-i-round

  1. For the source-divers, the error is raised here: https://github.com/ruby/bigdecimal/blob/1cb095003939db9e60d61982a9119247718c4349/ext/bigdecimal/bigdecimal.c#L2316-L2318 because BigDecimal_to_i calls with always=1: https://github.com/ruby/bigdecimal/blob/1cb095003939db9e60d61982a9119247718c4349/ext/bigdecimal/bigdecimal.c#L1062 and it means that the error for infinity is raised always, no matter what mode is set.

I believe it's an expected behaviour. All we could do is add a small note in the docs to be more explicit. WDYT @mrkn ?

mrzasa avatar Aug 05 '22 13:08 mrzasa