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

Fix #divmod #3426

Merged
Merged

Conversation

denisdefreyne
Copy link
Contributor

@denisdefreyne denisdefreyne commented Oct 16, 2016

Two changes:

  • The first element of the tuple should be an integer (quotient rounded down), rather than a float containing the quotient itself.
  • Documentation for negative integer divmod is now correct, and has additional tests for the examples.

Before:

1.4.divmod(0.3)[0]
# => 4.6666…

After:

1.4.divmod(0.3)[0]
# => 4

The first element of the tuple should be an integer (quotient rounded
down), rather than a float containing the quotient itself.

assert { 1.4.divmod(0.3)[0].should eq(4) }
assert { 1.4.divmod(0.3)[1].should be_close(0.2, 0.00001) }
end
Copy link
Contributor

Choose a reason for hiding this comment

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

Are the results this code will get for negative numbers considered? As it stands, it doesn't look like that, considering that the commit message claims the numbers are rounded down (which is not true - they are rounded towards 0) and that there are no tests for the negative case.

As a comparison, Numeric#divmod in Ruby is defined to round towards -infinity.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ahh, good point—I did not have that in mind. I’ll add some more test cases and fix the implementation.

@@ -158,7 +158,7 @@ struct Number
# 11.divmod(-3) # => {-3, 2}
Copy link
Contributor

Choose a reason for hiding this comment

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

Interestingly enough, in Ruby this gives:

11.divmod -3
=> [-4, -1]

Copy link
Member

Choose a reason for hiding this comment

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

I'm pretty sure Python's behavior completely matches Ruby's behavior. They should be closely followed.

@denisdefreyne denisdefreyne changed the title Fix #divmod for Float Fix #divmod Oct 16, 2016
@denisdefreyne
Copy link
Contributor Author

denisdefreyne commented Oct 16, 2016

I’ve updated the divmod tests, documentation and implementation to (hopefully) account for all cases.

The behavior of divmod is unfortunately up for discussion. For example, 11.divmod(-3) could be implemented as returning {-4, -1} (rounding towards -infinity) or {-3, 2} (rounding towards 0), and both are valid. (Ruby does the former.)

@oprypin
Copy link
Member

oprypin commented Oct 16, 2016

Before:

11.divmod(-3)
# => {-3, 2}

That is not true, only the example in the documentation was wrong. The PR doesn't change this behavior.

The first element of the tuple should be an integer

No, it shouldn't be an actual Int, because some Floats don't fit into an Int. But the PR uses floor which does actually return a Float, so all is good.


I completely agree with this pull request now, it doesn't change any behavior that was correct, and only fixes the output for Floats. The behavior matches that of Ruby and Python.

@denisdefreyne
Copy link
Contributor Author

Correct, my bad! I’ll update the description.

@asterite asterite added kind:bug A bug in the code. Does not apply to documentation, specs, etc. topic:stdlib labels Oct 17, 2016
@asterite
Copy link
Member

@ddfreyne Thank you!!

@asterite asterite merged commit ae551e9 into crystal-lang:master Oct 17, 2016
@denisdefreyne denisdefreyne deleted the denis/bug/float-divmod-int branch October 17, 2016 18:25
@chocolateboy
Copy link
Contributor

chocolateboy commented Oct 17, 2016

Looks like the second example in the documentation was missed:

python

divmod(11, -3) # => (-4, -1)

ruby

11.divmod(-3) # => [-4, -1]

crystal

11.divmod(-3) # => {-4, -1}

documentation

# 11.divmod(-3) # => {-4, 1}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. topic:stdlib
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants