summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Grebennicov <denis.grebennicov@mongodb.com>2022-08-17 17:24:20 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-10-06 16:59:29 +0000
commit26350ca57b016f0fa755d4cd8034bf5e491242b2 (patch)
treee4bea30cfae2ce65dd932ccb312e18a381a3956c
parent19912e29a71943349ce86066166cfd7fc14ea79d (diff)
downloadmongo-26350ca57b016f0fa755d4cd8034bf5e491242b2.tar.gz
SERVER-68233 MongoShell numberDecimalsAlmostEqual(NumberDecimal(0), NumberDecimal(0)) returns false
-rw-r--r--jstests/decimal/decimal_constructors.js45
-rw-r--r--src/mongo/shell/shell_utils.cpp22
2 files changed, 44 insertions, 23 deletions
diff --git a/jstests/decimal/decimal_constructors.js b/jstests/decimal/decimal_constructors.js
index c4611385b8a..0d3ff990f7b 100644
--- a/jstests/decimal/decimal_constructors.js
+++ b/jstests/decimal/decimal_constructors.js
@@ -50,36 +50,36 @@ assert.throws(() => numberDecimalsEqual(NumberDecimal('10.20'), "Wrong parameter
// Verify the behavior of 'numberDecimalsAlmostEqual' helper.
assert(numberDecimalsAlmostEqual(NumberDecimal("10001"), NumberDecimal("10002"), 3));
-assert.neq(numberDecimalsAlmostEqual(NumberDecimal("10001"), NumberDecimal("10002"), 5));
+assert(!numberDecimalsAlmostEqual(NumberDecimal("10001"), NumberDecimal("10002"), 5));
// Regression tests for BF-24149.
assert(numberDecimalsAlmostEqual(NumberDecimal("905721242210.0455427920454969568"),
NumberDecimal("905721242210.0453137831269007622941"),
15));
-assert.neq(numberDecimalsAlmostEqual(NumberDecimal("905721242210.0455427920454969568"),
- NumberDecimal("905721242210.0453137831269007622941"),
- 16));
+assert(!numberDecimalsAlmostEqual(NumberDecimal("905721242210.0455427920454969568"),
+ NumberDecimal("905721242210.0453137831269007622941"),
+ 16));
// Verify helper works the same with negative numers.
assert(numberDecimalsAlmostEqual(NumberDecimal("-10001"), NumberDecimal("-10002"), 3));
-assert.neq(numberDecimalsAlmostEqual(NumberDecimal("-10001"), NumberDecimal("-10002"), 5));
+assert(!numberDecimalsAlmostEqual(NumberDecimal("-10001"), NumberDecimal("-10002"), 5));
assert(numberDecimalsAlmostEqual(NumberDecimal("-905721242210.0455427920454969568"),
NumberDecimal("-905721242210.0453137831269007622941"),
15));
-assert.neq(numberDecimalsAlmostEqual(NumberDecimal("-905721242210.0455427920454969568"),
- NumberDecimal("-905721242210.0453137831269007622941"),
- 16));
+assert(!numberDecimalsAlmostEqual(NumberDecimal("-905721242210.0455427920454969568"),
+ NumberDecimal("-905721242210.0453137831269007622941"),
+ 16));
// Verify mixed-sign arguments aren't equal.
-assert.neq(numberDecimalsAlmostEqual(NumberDecimal("10001"), NumberDecimal("-10002"), 3));
-assert.neq(numberDecimalsAlmostEqual(NumberDecimal("-10001"), NumberDecimal("10002"), 3));
-assert.neq(numberDecimalsAlmostEqual(NumberDecimal("-905721242210.0455427920454969568"),
- NumberDecimal("905721242210.0453137831269007622941"),
- 10));
-assert.neq(numberDecimalsAlmostEqual(NumberDecimal("905721242210.0455427920454969568"),
- NumberDecimal("-905721242210.0453137831269007622941"),
- 10));
+assert(!numberDecimalsAlmostEqual(NumberDecimal("10001"), NumberDecimal("-10002"), 3));
+assert(!numberDecimalsAlmostEqual(NumberDecimal("-10001"), NumberDecimal("10002"), 3));
+assert(!numberDecimalsAlmostEqual(NumberDecimal("-905721242210.0455427920454969568"),
+ NumberDecimal("905721242210.0453137831269007622941"),
+ 10));
+assert(!numberDecimalsAlmostEqual(NumberDecimal("905721242210.0455427920454969568"),
+ NumberDecimal("-905721242210.0453137831269007622941"),
+ 10));
// Regression test for BF-25335
assert(numberDecimalsAlmostEqual(NumberDecimal("-104735446372966662851.0135276410897"),
@@ -87,4 +87,17 @@ assert(numberDecimalsAlmostEqual(NumberDecimal("-104735446372966662851.013527641
10));
// Regression test for BF-25390
assert(numberDecimalsAlmostEqual(NumberDecimal("-331.0000000000"), NumberDecimal("-331"), 10));
+
+// Verify numberDecimalsAlmostEqual() works with 0.
+assert(numberDecimalsAlmostEqual(NumberDecimal("0"), NumberDecimal("0"), 10));
+assert(numberDecimalsAlmostEqual(NumberDecimal("0"), NumberDecimal("0.0000000000000001"), 10));
+assert(numberDecimalsAlmostEqual(NumberDecimal("0.0000000000000001"), NumberDecimal("0"), 10));
+assert(!numberDecimalsAlmostEqual(NumberDecimal("1.00000000000000"), NumberDecimal("1.1"), 10));
+assert(numberDecimalsAlmostEqual(
+ NumberDecimal("1.00000000000000"), NumberDecimal("1.00000000000001"), 10));
+assert(numberDecimalsAlmostEqual(NumberDecimal("Infinity"), NumberDecimal("Infinity"), 10));
+assert(!numberDecimalsAlmostEqual(NumberDecimal("Infinity"), NumberDecimal("-Infinity"), 10));
+assert(!numberDecimalsAlmostEqual(NumberDecimal("Infinity"), NumberDecimal("NaN"), 10));
+assert(numberDecimalsAlmostEqual(NumberDecimal("NaN"), NumberDecimal("NaN"), 10));
+assert(!numberDecimalsAlmostEqual(NumberDecimal("0"), NumberDecimal("0.000001"), 10));
}());
diff --git a/src/mongo/shell/shell_utils.cpp b/src/mongo/shell/shell_utils.cpp
index cb82f223f9b..abdbb179bfa 100644
--- a/src/mongo/shell/shell_utils.cpp
+++ b/src/mongo/shell/shell_utils.cpp
@@ -521,14 +521,22 @@ BSONObj numberDecimalsAlmostEqual(const BSONObj& input, void*) {
auto ten = Decimal128(10);
auto exponent = a.toAbs().logarithm(ten).round();
- // Return early if arguments are not the same order of magnitude.
- if (exponent != b.toAbs().logarithm(ten).round()) {
- return BSON("" << false);
- }
+ // Early exit for zero, infinity and NaN cases.
+ if ((a.isZero() && b.isZero()) || (a.isNaN() && b.isNaN()) ||
+ (a.isInfinite() && b.isInfinite() && (a.isNegative() == b.isNegative()))) {
+ return BSON("" << true /* isErrorAcceptable */);
+ } else if (!a.isZero() && !b.isZero()) {
+ // Return early if arguments are not the same order of magnitude.
+ if (exponent != b.toAbs().logarithm(ten).round()) {
+ return BSON("" << false);
+ }
- // Put the whole number behind the decimal point.
- a = a.divide(ten.power(exponent));
- b = b.divide(ten.power(exponent));
+ // Put the whole number behind the decimal point.
+ if (!exponent.isZero()) {
+ a = a.divide(ten.power(exponent));
+ b = b.divide(ten.power(exponent));
+ }
+ }
auto places = third.numberDecimal();
auto isErrorAcceptable = a.subtract(b)