-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
Minor - P4
-
None
-
Affects Version/s: bson-6.10.4
-
Component/s: BSON
Here is a minimal example of the problem
What happens: Decimal128.toString() produces a string with 35 digits of precision
Expected behavior: Serialize to a string with a maximum 34 digits of precision
Effects of the problem:
- Unable to reconstruct a Decimal128 from the string
- The string representation is actually incorrect because Decimal128 is specifically designed to represent 34 digits, not 35. There is no 35th digit represented, so the final digit is necessarily wrong/nonexistent
import { Decimal128 } from "bson"; const assertions = [] function removeDecimalPoint(str: string): string { return str.replace(".", ""); } function truncateByOne(str: string): string { return str.slice(0, -1); } const bytes = Buffer.from("b2d734fc610c88c439e6222a4fed0330", "hex"); const d128 = new Decimal128(bytes); const str = d128.toString(); function constructs(str: string): Decimal128 | Error { try { return Decimal128.fromString(str); } catch (e) { return e; } } assertions.push(str === "1000.5500000000000682121026329696178") const constructionResult = constructs(str) as Error; assertions.push(constructionResult instanceof Error) const errorMessage = (constructionResult as Error).message; assertions.push(errorMessage === "\"1000.5500000000000682121026329696178\" is not a valid Decimal128 string - inexact rounding") //The decimal128 format supports 34 decimal digits of significand - https://en.wikipedia.org/wiki/Decimal128_floating-point_format#Format assertions.push(removeDecimalPoint(str).length === 35) // It works with one digit removed const truncatedStr = truncateByOne(str); assertions.push(truncatedStr === "1000.550000000000068212102632969617") // missing final 8 const truncatedConstructionResult = constructs(truncatedStr) as Decimal128; assertions.push(truncatedConstructionResult instanceof Decimal128); let i = 1; for (const assertion of assertions) { if (!assertion) { // This won't happen. Assertions will pass console.error(`❌ Assertion ${i} failed`); process.exit(1); } i++; } console.log("✅ All assertions passed"); process.exit(0);
- is related to
-
GODRIVER-3765 Non-canonical Decimal128 serializes incorrectly
-
- Closed
-
- related to
-
SERVER-115866 Specific Decimal128 bytes produce incorrect behavior
-
- Needs Scheduling
-
-
GODRIVER-3541 Validate raw-bit Decimal128 constructor to reject illegal patterns
-
- Backlog
-