Skip to content

Commit

Permalink
Merge pull request #1808 from robin850/bigdecimal-round
Browse files Browse the repository at this point in the history
Fix BigDecimal#round behavior with NAN and INFINITY
  • Loading branch information
headius committed Jul 25, 2014
2 parents 3ada3d9 + faae599 commit 7211c60
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 0 deletions.
22 changes: 22 additions & 0 deletions core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java
Expand Up @@ -1559,6 +1559,28 @@ public IRubyObject round(IRubyObject[] args) {
@JRubyMethod(name = "round", optional = 2)
public IRubyObject round(ThreadContext context, IRubyObject[] args) {
int scale = args.length > 0 ? num2int(args[0]) : 0;

// Special treatment for BigDecimal::NAN and BigDecimal::INFINITY
//
// If round is called without any argument, we should raise a
// FloatDomainError. Otherwise, we don't have to call round ;
// we can simply return the number itself.
if (scale == 0 && (isNaN() || isInfinity())) {
StringBuilder message = new StringBuilder("Computation results to ");
message.append("'").append(callMethod(context, "to_s")).append("'");

// To be consistent with MRI's output
if (isNaN()) message.append("(Not a Number)");

throw getRuntime().newFloatDomainError(message.toString());
} else {
if (isNaN()) {
return newNaN(context.runtime);
} else if (isInfinity()) {
return newInfinity(context.runtime, infinitySign);
}
}

RoundingMode mode = (args.length > 1) ? javaRoundingModeFromRubyRoundingMode(context.runtime, args[1]) : getRoundingMode(context.runtime);
// JRUBY-914: Java 1.4 BigDecimal does not allow a negative scale, so we have to simulate it
RubyBigDecimal bigDecimal = null;
Expand Down
12 changes: 12 additions & 0 deletions test/externals/ruby1.9/bigdecimal/test_bigdecimal.rb
Expand Up @@ -802,6 +802,18 @@ def test_round
end
end

def test_round_with_nan_and_infinity
[BigDecimal::NAN, BigDecimal::INFINITY, -BigDecimal::INFINITY].each do |number|
assert_raise(FloatDomainError) { number.round }
end
end

def test_round_with_precision_on_nan_and_infinity
assert_equal(true, BigDecimal::NAN.round(1).nan?)
assert_equal(BigDecimal::INFINITY, BigDecimal::INFINITY.round(1))
assert_equal(-BigDecimal::INFINITY, -BigDecimal::INFINITY.round(1))
end

def test_truncate
assert_equal(3, BigDecimal.new("3.14159").truncate)
assert_equal(8, BigDecimal.new("8.7").truncate)
Expand Down

0 comments on commit 7211c60

Please sign in to comment.