Skip to content

fix: compare integral numbers exactly instead of via double - #843

Merged
ebussieres merged 1 commit into
PebbleTemplates:masterfrom
princejain756:fix/large-number-comparisons
Oct 19, 2026
Merged

ebussieres merged 1 commit into
PebbleTemplates:masterfrom
princejain756:fix/large-number-comparisons

Conversation

@princejain756

Copy link
Copy Markdown
Contributor

Closes #595.

What was broken

wideningConversionBinaryComparison routed every operand through doubleValue(), so 325055142682428416 == 325055142682428417 evaluated to true in templates (both collapse to the same double above 2^53). Related, wideningConversionBinaryOperation sent BigInteger operands through integerOperation (intValue() truncation) and converted BigDecimal pairs via doubleValue(), losing precision for integral inputs.

Fix

Mirroring Java's numeric promotion in wideningConversionBinaryComparison:

  • BigDecimal/BigInteger operand → exact compareTo
  • Double/Float operand → double comparison (unchanged)
  • otherwise integral (Long/Integer/Short/Byte) → exact long comparison

In wideningConversionBinaryOperation: BigInteger now joins the BigDecimal branch, and the operand conversion uses toString-based toBigDecimal (exact for integral inputs, identical to BigDecimal.valueOf for doubles).

Tests

Three new cases in OperatorUtilsTest: large-long equality/ordering, BigInteger+BigDecimal exactness, and BigInteger + 1 no longer wrapping past Long.MAX_VALUE. mvn -pl pebble test: 1012 tests, 19 failures all in EmbedTagTest, which fails identically on a clean checkout (missing embed resources in this environment).

Number comparisons routed every operand through doubleValue(), so two
distinct values above 2^53 compared equal: 325055142682428416 == ...417
evaluated true. Integral pairs (Long, Integer, Short, Byte) now compare
with longComparison, BigDecimal/BigInteger via compareTo, and only
floating-point operands keep the double path, matching Java's own
numeric promotion.

Binary operations route BigInteger through bigDecimalOperation too;
previously it fell through to integerOperation and wrapped on intValue.
The BigDecimal operand conversion now uses toString instead of
doubleValue, keeping exact precision for integral inputs.

Closes PebbleTemplates#595
@ebussieres ebussieres added this to the 4.1.3 milestone Oct 19, 2026
@ebussieres
ebussieres merged commit 5da0832 into PebbleTemplates:master Oct 19, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Long, BigInteger, BigDecimal Operators Fail Due to Conversion to Double

2 participants