public static boolean equal(Number lhs, Number rhs) {
        Class lhsClass = lhs.getClass();
        Class rhsClass = rhs.getClass();
        assert lhsClass != rhsClass;

        if (isDoubleRepresentable(lhsClass)) {
            if (isDoubleRepresentable(rhsClass)) {
                return equalDoubles(lhs.doubleValue(), rhs.doubleValue());
            } else if (isLongRepresentable(rhsClass)) {
                return equalLongAndDouble(rhs.longValue(), lhs.doubleValue());
            }
        } else if (isLongRepresentable(lhsClass)) {
            if (isDoubleRepresentable(rhsClass)) {
                return equalLongAndDouble(lhs.longValue(), rhs.doubleValue());
            } else if (isLongRepresentable(rhsClass)) {
                return lhs.longValue() == rhs.longValue();
            }
        }

        return lhs.equals(rhs);
    }
@Test
    public void testEqual() {
        assertNotEqual(1L, 2);
        assertEqual(1, 1L);
        assertEqual(1, (short) 1);
        assertEqual(1, (byte) 1);

        assertNotEqual(new AtomicLong(1), new AtomicInteger(1));

        assertNotEqual(1, 1.1);
        // 1.100000000000000088817841970012523233890533447265625 != 1.10000002384185791015625
        assertNotEqual(1.1, 1.1F);
        assertEqual(1, 1.0);
        assertEqual(1, 1.0F);
        assertEqual(1.0F, 1.0);
        assertEqual(1.5F, 1.5);
        assertEqual(1.1F, (double) 1.1F);

        assertEqual(0, 0.0);
        assertNotEqual(0, -0.0);
        assertNotEqual(Long.MIN_VALUE, Double.NEGATIVE_INFINITY);
        assertNotEqual(Long.MAX_VALUE, Double.POSITIVE_INFINITY);
        assertNotEqual(0, Double.NaN);

        assertNotEqual(Long.MAX_VALUE, Long.MAX_VALUE + 5000.0);
        assertNotEqual(Long.MIN_VALUE, Long.MIN_VALUE - 5000.0);

        assertEqual(1L << 53, 0x1p53);
        // with Double, all things are possible
        assertEqual(1L << 53, 0x1p53 + 1);
        assertNotEqual(1L << 53, 0x1p53 - 1);
        assertEqual((1L << 53) - 1, 0x1p53 - 1);
        assertEqual((1L << 53) + 2, 0x1p53 + 2);

        assertEqual(-(1L << 53), -0x1p53);
        assertEqual(-(1L << 53), -0x1p53 - 1);
        assertNotEqual(-(1L << 53), -0x1p53 + 1);
        assertEqual(-(1L << 53) + 1, -0x1p53 + 1);
        assertEqual(-(1L << 53) - 2, -0x1p53 - 2);

        assertNotEqual(Integer.MAX_VALUE, Long.MAX_VALUE);
        assertNotEqual(Integer.MIN_VALUE, Long.MIN_VALUE);
    }