DevHeads.net

Behaviour of round changed?

I am moving some algorithms between 1.9.3 and 2.4.2 and found (after much
head scratching)

2.4.2 :001 > 1.015.round(2)
=> 1.02

1.9.3-p551 :001 > 1.015.round(2)
=> 1.01

We are calculating margin prices and round input values to 2 places because
the precision is not needed and it can help with caching

The tests broke :(

Let me see if I understand this, Ruby has changed how basic maths functions
work

Can I trust ceil, floor, truncate or any of the other number related
functions?

Do I need to write tests for the language itself for when I upgrade to a
newer version in the future or should I stick with 1.9.3 for all eternity?

A change at this low a level is almost impossible to speculatively test
for, if I cannot trust the language I am using I cannot trust my code at all

I am now in a position of having to test my code to an excessive degree
because I cannot trust there are not any other changes that will be
triggered on some previously innocent edge case

I am extremely pissed off right now

Comments

Re: Behaviour of round changed?

By Greg Navis at 01/08/2019 - 10:06

Let me emphasize what Matthew already said: you should never, ever use
floats to represent money. Rounding, lack of precision, comparisons - all
that makes floats unreliable for dealing with monetary amounts.

Best regards
Greg Navis

Re: Behaviour of round changed?

By Peter Hickman at 01/08/2019 - 10:52

Thanks, I get the money thing but this is price as used in calculating odds
in betting. Price is an idealised value, not monetary (no accountants
involved :))

The calculation needs to be reliable. Given a set of inputs is should
return the same outputs. In this situation we have code changing it's
outputs depending on which version of Ruby is running it

I'm glad that it is just round that has been affected and that it was a
conscious decision but I have some not inconsiderable blobs of maths for
pricing (in betting) and libraries that are used to support it

I can grep for round but the thought that I couldn't trust any number based
function is truly terrifying

Re: Behaviour of round changed?

By Xavier Noria at 01/08/2019 - 11:18

On Tue, Jan 8, 2019 at 3:53 PM Peter Hickman < ... at googlemail dot com>
wrote:

Thanks, I get the money thing but this is price as used in calculating odds
I once worked on a betting platform and chose rationals all the way down to
Postgres :)

<a href="https://www.youtube.com/watch?v=tT72TlmhgL4" title="https://www.youtube.com/watch?v=tT72TlmhgL4">https://www.youtube.com/watch?v=tT72TlmhgL4</a>

Maybe your choice is good, can't tell without knowing the details, but be
super vigilant of the assumptions!

RE: Behaviour of round changed?

By Andy Jones at 01/08/2019 - 09:56

IIRC it’s just round. A decision was made to round to the nearest even number in case of a tie, rather than to round down. This is the more standard approach?

I think this is the relevant issue: <a href="https://bugs.ruby-lang.org/issues/12548" title="https://bugs.ruby-lang.org/issues/12548">https://bugs.ruby-lang.org/issues/12548</a>

I am moving some algorithms between 1.9.3 and 2.4.2 and found (after much head scratching)

2.4.2 :001 > 1.015.round(2)
=> 1.02

1.9.3-p551 :001 > 1.015.round(2)
=> 1.01

We are calculating margin prices and round input values to 2 places because the precision is not needed and it can help with caching

The tests broke :(

Let me see if I understand this, Ruby has changed how basic maths functions work

Can I trust ceil, floor, truncate or any of the other number related functions?

Do I need to write tests for the language itself for when I upgrade to a newer version in the future or should I stick with 1.9.3 for all eternity?

A change at this low a level is almost impossible to speculatively test for, if I cannot trust the language I am using I cannot trust my code at all

I am now in a position of having to test my code to an excessive degree because I cannot trust there are not any other changes that will be triggered on some previously innocent edge case

I am extremely pissed off right now

Click here to view Company Information and Confidentiality Notice.<http://www.jameshall.co.uk/index.php/small-print/email-disclaimer>

Please note that we have updated our privacy policy in line with new data protection regulations. Please refer to our website to view the ways in which we handle your data.

Re: Behaviour of round changed?

By Matthew Kerwin at 01/08/2019 - 09:55

It's late here, so I can only be quick:

1. Don't ever use floats for money.

2. It was documented in the release notes for 2.4.0
<https://docs.ruby-lang.org/en/2.4.0/NEWS.html>

"Float#round now takes an optional keyword argument, half option,
and the default behavior is round-to-nearest-even now. [Bug #12548]"

3. See these tickets in the bug tracker for some history on the #round changes:

* <a href="https://bugs.ruby-lang.org/issues/12548" title="https://bugs.ruby-lang.org/issues/12548">https://bugs.ruby-lang.org/issues/12548</a>
* <a href="https://bugs.ruby-lang.org/issues/12958" title="https://bugs.ruby-lang.org/issues/12958">https://bugs.ruby-lang.org/issues/12958</a>
* <a href="https://bugs.ruby-lang.org/issues/12953" title="https://bugs.ruby-lang.org/issues/12953">https://bugs.ruby-lang.org/issues/12953</a>

4. Even Ruby 2.4 is old now; 2.6.0 has been released...

5. Don't ever use floats for money.

Cheers

On Tue, 8 Jan 2019 at 23:17, Peter Hickman
< ... at googlemail dot com> wrote: