From 072d6df374f92fc7545d4e0ebe2a04f30a79a868 Mon Sep 17 00:00:00 2001 From: PHJ2000 <105151063+PHJ2000@users.noreply.github.com> Date: Mon, 5 Oct 2026 22:43:13 +0900 Subject: [PATCH] Preserve precision when comparing numbers of the same type --- .../handlebars/helper/ConditionalHelpers.java | 6 ++ .../helper/ConditionalHelpersTest.java | 58 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 handlebars/src/test/java/com/github/jknack/handlebars/helper/ConditionalHelpersTest.java diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/helper/ConditionalHelpers.java b/handlebars/src/main/java/com/github/jknack/handlebars/helper/ConditionalHelpers.java index 0633b9dc..5e8e3d21 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/helper/ConditionalHelpers.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/helper/ConditionalHelpers.java @@ -423,6 +423,12 @@ protected boolean eq(final Object a, final Object b) { boolean value = Objects.equals(a, b); if (!value) { if (a instanceof Number && b instanceof Number) { + if (a.getClass() == b.getClass() + && a instanceof Comparable + && !(a instanceof Double) + && !(a instanceof Float)) { + return cmp(a, b) == 0; + } // int vs double: 2 vs 2.0 return ((Number) a).doubleValue() == ((Number) b).doubleValue(); } diff --git a/handlebars/src/test/java/com/github/jknack/handlebars/helper/ConditionalHelpersTest.java b/handlebars/src/test/java/com/github/jknack/handlebars/helper/ConditionalHelpersTest.java new file mode 100644 index 00000000..38bacc48 --- /dev/null +++ b/handlebars/src/test/java/com/github/jknack/handlebars/helper/ConditionalHelpersTest.java @@ -0,0 +1,58 @@ +/* + * Handlebars.java: https://github.com/jknack/handlebars.java + * Apache License Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 + * Copyright (c) 2012 Edgar Espina + */ +package com.github.jknack.handlebars.helper; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import org.junit.jupiter.api.Test; + +import com.github.jknack.handlebars.Handlebars; + +public class ConditionalHelpersTest { + @Test + public void compareLargeLongsWithoutRounding() throws IOException { + Handlebars handlebars = new Handlebars().registerHelpers(ConditionalHelpers.class); + assertEquals( + "false/true", + handlebars + .compileInline("{{eq a b}}/{{neq a b}}") + .apply(Map.of("a", 9007199254740992L, "b", 9007199254740993L))); + assertFalse(ConditionalHelpers.eq.eq(Long.MAX_VALUE, Long.MAX_VALUE - 1)); + assertTrue(ConditionalHelpers.eq.eq(Long.MAX_VALUE, Long.MAX_VALUE)); + } + + @Test + public void compareBigNumbersWithoutRounding() { + assertFalse( + ConditionalHelpers.eq.eq( + new BigInteger("9007199254740992"), new BigInteger("9007199254740993"))); + assertFalse( + ConditionalHelpers.eq.eq( + new BigDecimal("1.00000000000000001"), new BigDecimal("1.00000000000000002"))); + assertFalse(ConditionalHelpers.eq.eq(new BigDecimal("1e-400"), new BigDecimal("2e-400"))); + assertTrue(ConditionalHelpers.eq.eq(new BigDecimal("2.0"), new BigDecimal("2.00"))); + } + + @Test + public void preserveOtherNumericComparisons() { + assertTrue(ConditionalHelpers.eq.eq(2, 2.0)); + assertTrue(ConditionalHelpers.eq.eq(0.0, -0.0)); + assertTrue(ConditionalHelpers.eq.eq(0.0f, -0.0f)); + assertTrue(ConditionalHelpers.eq.eq(Double.NaN, Double.NaN)); + assertTrue(ConditionalHelpers.eq.eq(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY)); + assertTrue(ConditionalHelpers.eq.eq(new AtomicLong(2), new AtomicLong(2))); + assertFalse(ConditionalHelpers.eq.eq(null, 2)); + assertFalse(ConditionalHelpers.eq.eq("2", 2)); + } +}