Skip to content

Allow BigDecimal accept Float without precision #314

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

Merged
merged 4 commits into from
Jun 10, 2025

Conversation

mrzasa
Copy link
Contributor

@mrzasa mrzasa commented Feb 4, 2025

Make sure that conversion from a Float works consistently with the conversion from a string representing that float.

Current master state:

pry(main)> BigDecimal(1.2)
ArgumentError: can't omit precision for a Float.
from (pry):22:in `BigDecimal'
pry(main)> BigDecimal('1.2')
=> 0.12e1

After this changes:

pry(main)> BigDecimal(1.2)
=> 0.12e1
pry(main)> BigDecimal('1.2')
=> 0.12e1

When precision is omitted it's set to 0.

Fixes #213
Blocked by #313

@mrzasa mrzasa marked this pull request as ready for review February 4, 2025 23:08
@mrkn mrkn force-pushed the float-without-precision branch from 8850458 to 8cdf5cd Compare May 14, 2025 09:49
@@ -166,7 +166,8 @@ def test_BigDecimal_with_float
assert_equal(BigDecimal("0.1235"), BigDecimal(0.1234567, 4))
assert_equal(BigDecimal("-0.1235"), BigDecimal(-0.1234567, 4))
assert_equal(BigDecimal("0.01"), BigDecimal(0.01, Float::DIG + 1))
assert_raise_with_message(ArgumentError, "can't omit precision for a Float.") { BigDecimal(4.2) }
assert_nothing_raised { BigDecimal(4.2) }
assert_equal(BigDecimal(4.2), BigDecimal('4.2'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrzasa Could you add more assertions to check many cases, especially for numbers that don't have accurate representations in Float?
Moreover, we must compare two values by assert_in_delta and pass an appropriate value to the delta argument for the original Float value; it should be 0.5ulp.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reconsidered how to check here.

I suggest comparing the result of to_f with the original Float value, like this: assert_equal(4.2, BigDecimal(4.2).to_f).
This approach is preferable because it doesn’t depend on the specific decimal representation for a given Float value. I’d like to avoid relying on the particular algorithm used for converting a Float to a BigDecimal.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a same test case as BigDecimal(float, 0) is enough.
But since test for BigDecimal(float, 0) is currently missing, adding both will be nice.

assert_equal(BigDecimal("string representation"), BigDecimal(float_literal_here, 0))
assert_equal(BigDecimal("string representation"), BigDecimal(float_literal_here))

# Just like this one on line 166-168
assert_equal(BigDecimal("0.1235"), BigDecimal(0.1234567, 4))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I've added the floats test cases

Copy link
Member

@tompng tompng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. looks good 👍

Perhaps some tests for BigDecimal(x, various_number) are missing, some test are too strict.

# this test is too strict
assert_equal(BigDecimal("0.01"), BigDecimal(0.01, Float::DIG + 1))
# because:
BigDecimal(0.07, Float::DIG + 1) #=> 0.7000000000000001e-1

but let's consider it a separate issue of test.

@tompng tompng merged commit 57e0d40 into ruby:master Jun 10, 2025
78 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BigDecimal should accept a Float value without a precision
4 participants