[CDRIVER-3377] Double value retrieved from bson is different than expected Created: 27/Sep/19 Updated: 29/Jan/24 Resolved: 22/Oct/19 |
|
| Status: | Closed |
| Project: | C Driver |
| Component/s: | libbson |
| Affects Version/s: | 1.13.0 |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Aziz Zitouni | Assignee: | Jeremy Mikola |
| Resolution: | Works as Designed | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||||||||||
| Description |
|
Example code:
Actual output:
Expected output:
|
| Comments |
| Comment by Jeremy Mikola [ 22/Oct/19 ] | |||||||||||||||||||||||||||||||||||||||||||||
|
Closing this as I don't believe there are any libbson changes to make based on my previous response. Using a Decimal128 type is likely the best way to avoid any issues with inexact representations using normal float types. | |||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jeremy Mikola [ 30/Sep/19 ] | |||||||||||||||||||||||||||||||||||||||||||||
|
I believe this is closely tied to the inability to exactly represent decimal binaries in binary floating point (as discussed in this Stack Overflow thread). I'll lead with noting that MongoDB provides a Decimal128 BSON type specifically to overcome this issue, and I'll revisit that later in this post. The original format string was "%lf" and dates back to libbson's original commit (f3911ed). This was later changed to "%.15g" in 9eb14d1 for Reading through I tested this with a few different patterns using a modified version of the program you shared:
I observed the following output running this program:
Based on that output, one would assume that a simple "%g" format might achieve what you're looking for; however, further testing revealed possible adverse side effects of not specifying a precision modifier with "%g". Using "%g" alone with "1.0000001" prints "1" and truncates the fraction. If you are attempting to model monetary data, I might suggest using the Decimal128 BSON type instead of a floating point value. That BSON type will ensure a completely accurate representation of your floating point value. It may also require an extra step when parsing JSON output, since the value will be reported as a string value in an object with a "$numberDecimal" key (similar to the canonical output for floating points above, which uses "$numberDouble"). |