Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BigDecimal#round raises FloatDomainError regardless of exception mode #226

Open
mrkn opened this issue Apr 20, 2022 · 2 comments
Open

BigDecimal#round raises FloatDomainError regardless of exception mode #226

mrkn opened this issue Apr 20, 2022 · 2 comments

Comments

@mrkn
Copy link
Member

mrkn commented Apr 20, 2022

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>'
@mrzasa
Copy link
Contributor

mrzasa commented Aug 5, 2022

  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:
    if (round_to_int) {
    return BigDecimal_to_i(VpCheckGetValue(c));
    }

    because BigDecimal_to_i calls with always=1:
    GUARD_OBJ(p, GetVpValue(self, 1));

    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 ?

@TomNaessens
Copy link

Same happens for NaN, looks like another side effect of the same case:

irb(main):029:0> BigDecimal('NaN').round(1)
=> NaN

irb(main):031:0> BigDecimal('NaN').round(0)
(irb):31:in `round`: Computation results to 'NaN'(Not a Number) (FloatDomainError)

irb(main):032:0> BigDecimal('NaN').round(-1)
(irb):32:in `round`: Computation results to 'NaN'(Not a Number) (FloatDomainError)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants