Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions sjsonnet/src/sjsonnet/DecimalFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,23 @@ object DecimalFormat {
case None =>
val precision = zeroes + hashes
if (precision == 0) {
// No fractional digits needed - just round and format the integer part
val rounded = math.rint(number)
// Round half away from zero (matching go-jsonnet/jrsonnet behavior)
val rounded = if (number >= 0) math.floor(number + 0.5) else math.ceil(number - 0.5)
val prefix =
if (rounded.isInfinite || math.abs(rounded) > Long.MaxValue)
BigDecimal(rounded).toBigInt.toString
else rounded.toLong.toString
if (alternate) prefix + "." else prefix
} else {
val denominator = BigDecimal(10).pow(precision)
val bd = BigDecimal(number)
val bd = BigDecimal(number).abs
val scaled =
(bd * denominator + BigDecimal("0.5")).setScale(0, BigDecimal.RoundingMode.FLOOR)
val wholeBD = (scaled / denominator).setScale(0, BigDecimal.RoundingMode.FLOOR)
val fracBD = (scaled - wholeBD * denominator).abs

val prefix = wholeBD.toBigInt.toString
val sign = if (number < 0) "-" else ""
val prefix = sign + wholeBD.toBigInt.toString
val fracStr = fracBD.toBigInt.toString

val frac =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Verify std.format uses round-half-away-from-zero (matching go-jsonnet/jrsonnet).
// Previously used HALF_EVEN (banker's rounding) which gave wrong results for .5 values.

std.assertEqual(std.format("%.0f", [0.5]), "1") &&
std.assertEqual(std.format("%.0f", [1.5]), "2") &&
std.assertEqual(std.format("%.0f", [2.5]), "3") &&
std.assertEqual(std.format("%.0f", [3.5]), "4") &&
std.assertEqual(std.format("%.0f", [4.5]), "5") &&
std.assertEqual(std.format("%.0f", [-0.5]), "-1") &&
std.assertEqual(std.format("%.0f", [-1.5]), "-2") &&
std.assertEqual(std.format("%.0f", [-2.5]), "-3") &&
// Higher precision
std.assertEqual(std.format("%.1f", [0.25]), "0.3") &&
std.assertEqual(std.format("%.1f", [0.35]), "0.4") &&
std.assertEqual(std.format("%.1f", [-0.25]), "-0.3") &&
std.assertEqual(std.format("%.2f", [0.005]), "0.01") &&
std.assertEqual(std.format("%.2f", [0.015]), "0.02") &&
std.assertEqual(std.format("%.2f", [-0.005]), "-0.01") &&
// Carry case: rounding causes integer part to increment
std.assertEqual(std.format("%.2f", [9.999]), "10.00") &&
// Negative rounding to zero
std.assertEqual(std.format("%.2f", [-0.001]), "-0.00") &&
true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
true
Loading