JRuby

JRuby's BigDecimal needs to round

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: JRuby 0.9.9, JRuby 1.0.0RC1, JRuby 1.0.0RC2
  • Fix Version/s: JRuby 1.0.0RC3
  • Component/s: Core Classes/Modules
  • Labels:
    None
  • Testcase included:
    yes
  • Number of attachments :
    2

Description

Patch implements method. This is needed to run unit tests in, e.g. Rails financial applications.

Activity

Hide
Ola Bini added a comment -

Thanks, Stuart!

Show
Ola Bini added a comment - Thanks, Stuart!
Hide
Ola Bini added a comment -

Sorry, Stuart, but the tests fail on 1.4 with this applied. I've reverted for now.

Show
Ola Bini added a comment - Sorry, Stuart, but the tests fail on 1.4 with this applied. I've reverted for now.
Hide
Charles Oliver Nutter added a comment -

Bumping to post-RC. We need a 1.4-compatible version of this to accept it.

Show
Charles Oliver Nutter added a comment - Bumping to post-RC. We need a 1.4-compatible version of this to accept it.
Hide
Stuart Halloway added a comment -

I see the tests passing on 1.5 and 1.4.2 on Mac OS X. What is the exact point release and OS where the tests can be seen failing?

Show
Stuart Halloway added a comment - I see the tests passing on 1.5 and 1.4.2 on Mac OS X. What is the exact point release and OS where the tests can be seen failing?
Hide
Nick Sieger added a comment -

Stu, the failing build can be seen here:

http://jruby.thresher.com/browse/JRUBY-MVN-357

The machine is a Solaris 10 x86 box, running 1.4.2_12. Does that help?

Show
Nick Sieger added a comment - Stu, the failing build can be seen here: http://jruby.thresher.com/browse/JRUBY-MVN-357 The machine is a Solaris 10 x86 box, running 1.4.2_12. Does that help?
Hide
Charles Oliver Nutter added a comment -

Ok, here's the deal. Negative scale appears to be a 1.5 feature. I have no explanation for why it works on OS X Java 1.4.2_12, but the official javadoc APIs explicitly state that in 1.4.2 a negative scale results in an ArithmeticError.

So we can probably get this fix in by checking for 1.5 or raising an ArgumentError with some explanation when running under 1.4.2. That's where it stands, and I'm punting it to post RC2 since it's not going to be done today. Hopefully still in 1.0.

Show
Charles Oliver Nutter added a comment - Ok, here's the deal. Negative scale appears to be a 1.5 feature. I have no explanation for why it works on OS X Java 1.4.2_12, but the official javadoc APIs explicitly state that in 1.4.2 a negative scale results in an ArithmeticError. So we can probably get this fix in by checking for 1.5 or raising an ArgumentError with some explanation when running under 1.4.2. That's where it stands, and I'm punting it to post RC2 since it's not going to be done today. Hopefully still in 1.0.
Hide
Stuart Halloway added a comment -

That's a bummer. When I first wrote the method I used 1.5+ only APIs. Then, realizing we needed to support 1.4.x, I switched to using scale, which apparently isn't flexible enough to do the work. If I have a chance I will look around to see how people solve this. Surely somebody else needs to round numbers...

Show
Stuart Halloway added a comment - That's a bummer. When I first wrote the method I used 1.5+ only APIs. Then, realizing we needed to support 1.4.x, I switched to using scale, which apparently isn't flexible enough to do the work. If I have a chance I will look around to see how people solve this. Surely somebody else needs to round numbers...
Hide
Charles Oliver Nutter added a comment -

Ok Stu, thanks. Just FYI, if you don't find a solution, this is likely to get punted to post 1.0. Even a solution that just produces a nice Ruby error for negative scale under 1.4 but works fine under 1.5 would probably be acceptable, but of course we'd like it to work everywhere.

Show
Charles Oliver Nutter added a comment - Ok Stu, thanks. Just FYI, if you don't find a solution, this is likely to get punted to post 1.0. Even a solution that just produces a nice Ruby error for negative scale under 1.4 but works fine under 1.5 would probably be acceptable, but of course we'd like it to work everywhere.
Hide
Erik van Oosten added a comment -

For Java 1.4 you can use IBM's BigDecimal which is free for use. IBM's implementation stood model for Java 5's implementation so its interface is pretty much identical (it has a different package).

Show
Erik van Oosten added a comment - For Java 1.4 you can use IBM's BigDecimal which is free for use. IBM's implementation stood model for Java 5's implementation so its interface is pretty much identical (it has a different package).
Hide
David Rupp added a comment -

BigDecimal.movePointLeft() and movePointRight() allow a negative index; you could use them to normalize/restore the number to be rounded. For example:

if scale < 0 {
return new RubyBigDecimal(getRuntime(), value.movePointRight(scale).setScale(0,mode).movePointLeft(scale))
// or whatever intermediate steps you want to use
} else {
// as before
}

Moving right by a negative index puts the 10's place to be rounded to directly to the left of the decimal point. Rounding with a scale of 0 does what you would expect. Then you shift everything back; movePointLeft with a negative index n has the effect of multiplying by 10^n, which puts everything back where it belongs.

I've verified this algorithm anecdotally (using Jython, of all things) on the two test cases in Stu's patch. Looks like it should be portable for 1.4/1.5. I'll leave it to you all to decide if it's worth pursuing for real, though.

Cheers,
David

Show
David Rupp added a comment - BigDecimal.movePointLeft() and movePointRight() allow a negative index; you could use them to normalize/restore the number to be rounded. For example: if scale < 0 { return new RubyBigDecimal(getRuntime(), value.movePointRight(scale).setScale(0,mode).movePointLeft(scale)) // or whatever intermediate steps you want to use } else { // as before } Moving right by a negative index puts the 10's place to be rounded to directly to the left of the decimal point. Rounding with a scale of 0 does what you would expect. Then you shift everything back; movePointLeft with a negative index n has the effect of multiplying by 10^n, which puts everything back where it belongs. I've verified this algorithm anecdotally (using Jython, of all things) on the two test cases in Stu's patch. Looks like it should be portable for 1.4/1.5. I'll leave it to you all to decide if it's worth pursuing for real, though. Cheers, David
Hide
David Rupp added a comment -

Okay, so I broke down and created a patch. This is just Stu's patch, plus my movePointLeft()/movePointRight() hack and some (unnecessary?) comments. I removed the "import java.math.*" statement from Stu's original, since I was able to compile without it. And I added some tests to exercise the negative scale with a couple more of the interesting rounding modes.

David

Show
David Rupp added a comment - Okay, so I broke down and created a patch. This is just Stu's patch, plus my movePointLeft()/movePointRight() hack and some (unnecessary?) comments. I removed the "import java.math.*" statement from Stu's original, since I was able to compile without it. And I added some tests to exercise the negative scale with a couple more of the interesting rounding modes. David
Hide
Charles Oliver Nutter added a comment -

Looks great, thanks again guys. Committed in 3721.

Show
Charles Oliver Nutter added a comment - Looks great, thanks again guys. Committed in 3721.

People

Vote (0)
Watch (2)

Dates

  • Created:
    Updated:
    Resolved: