Skip to content

Commit

Permalink
[fix] only round half-to-even when no tail left
Browse files Browse the repository at this point in the history
e.g.  0.25 -> 0.2   0.2500 -> 0.2   0.2501 -> 0.3

resolves jrubyGH-5556
  • Loading branch information
kares committed Jan 29, 2019
1 parent 7817954 commit af64c73
Showing 1 changed file with 26 additions and 11 deletions.
37 changes: 26 additions & 11 deletions core/src/main/java/org/jruby/util/Sprintf.java
Expand Up @@ -1636,24 +1636,39 @@ private static int skipSignBits(byte[] bytes, int base) {
return skip;
}

private static int round(byte[] bytes, int nDigits, int roundPos, boolean roundDown) {
int next = roundPos + 1;
if (next >= nDigits) return nDigits;
if (bytes[next] < '5') return nDigits;
if (roundDown && bytes[next] == '5' && next == nDigits - 1) return nDigits;
private static int round(byte[] bytes, final int nDigits, int roundPos, boolean roundDown) {
final int nextPos = roundPos + 1;
if (nextPos >= nDigits) return nDigits;
if (bytes[nextPos] < '5') return nDigits;

if (roundPos < 0) { // "%.0f" % 0.99
System.arraycopy(bytes, 0, bytes, 1, nDigits);
bytes[0] = '1';
return nDigits + 1;
}
// round half to even
if (roundPos + 1 < nDigits && bytes[roundPos + 1] == '5') {
if ((bytes[roundPos] - '0') % 2 == 0) {
// round down
return nDigits;

if (bytes[nextPos] == '5') {
if (nextPos == nDigits - 1) {
if (roundDown || (bytes[roundPos] - '0') % 2 == 0) {
return nDigits; // round down (half-to-even)
}
}
// we only need to apply half-to-even rounding
// if we're at last pos (^^ above) 0.25 -> 0.2
// or all that is left are zeros 0.2500 -> 0.2 but 0.2501 -> 0.3
int i = nextPos;
while (++i < nDigits) {
if (bytes[i] != '0') {
break;
}
}
if (i == nDigits - 1 && (bytes[i] == '0')) {
if ((bytes[roundPos] - '0') % 2 == 0) {
return nDigits; // round down (half-to-even)
}
}
}

bytes[roundPos] += 1;

while (bytes[roundPos] > '9') {
Expand All @@ -1662,7 +1677,7 @@ private static int round(byte[] bytes, int nDigits, int roundPos, boolean roundD
if (roundPos >= 0) {
bytes[roundPos] += 1;
} else {
System.arraycopy(bytes,0,bytes,1,nDigits);
System.arraycopy(bytes, 0, bytes, 1, nDigits);
bytes[0] = '1';
return nDigits + 1;
}
Expand Down

0 comments on commit af64c73

Please sign in to comment.