Skip to content

Commit 93c628d

Browse files
committed
fix GH-2524 on master: proper algorithm to set the precision
1 parent b3bfc9d commit 93c628d

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -869,10 +869,16 @@ public IRubyObject op_quo20(ThreadContext context, IRubyObject other) {
869869
}
870870

871871
private IRubyObject op_quo19_20(ThreadContext context, IRubyObject other) {
872-
RubyObject preciseOther = getVpValue19(context, other, true);
872+
RubyBigDecimal preciseOther = getVpValue19(context, other, true);
873873
// regular division with some default precision
874-
// TODO: proper algorithm to set the precision
875-
return op_div(context, preciseOther, getRuntime().newFixnum(200));
874+
// proper algorithm to set the precision
875+
// the precision is multiple of 4
876+
// and the precision is larger than len * 2
877+
int len = value.precision() + preciseOther.value.precision();
878+
int pow = len / 4;
879+
int precision = (pow + 1) * 4 * 2;
880+
881+
return op_div(context, preciseOther, getRuntime().newFixnum(precision));
876882
}
877883

878884
public IRubyObject op_div(ThreadContext context, IRubyObject other) {
@@ -923,10 +929,9 @@ public IRubyObject op_div(ThreadContext context, IRubyObject other, IRubyObject
923929
// MRI behavior: "If digits is 0, the result is the same as the / operator."
924930
if (scale == 0) return op_quo(context, other);
925931

926-
// TODO: better algorithm to set precision needed
927-
int prec = Math.max(200, scale);
932+
MathContext mathContext = new MathContext(scale, getRoundingMode(context.runtime));
928933
return new RubyBigDecimal(context.runtime,
929-
value.divide(val.value, new MathContext(prec, RoundingMode.HALF_UP))).setResult(scale);
934+
value.divide(val.value, mathContext)).setResult(scale);
930935
}
931936

932937
@JRubyMethod(name = "div")
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
require 'bigdecimal'
2+
3+
# https://github.com/jruby/jruby/issues/2524
4+
describe 'BigDecimal precision test with different execution order' do
5+
it 'returns same precision ' do
6+
fraction = BigDecimal.new("0.0095") / 365 * BigDecimal.new(50_000)
7+
r1 = fraction * BigDecimal.new(50_000) / BigDecimal.new(100_000)
8+
r2 = fraction * (BigDecimal.new(50_000) / BigDecimal.new(100_000))
9+
expect(r1).to eq(r2)
10+
end
11+
end
12+

0 commit comments

Comments
 (0)