[CSHARP-1969] BsonExtensionMethods.ToJson() lost precision with floating pointer numbers Created: 24/Apr/17 Updated: 29/Sep/20 Resolved: 29/Sep/20 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | BSON |
| Affects Version/s: | 2.4.3 |
| Fix Version/s: | None |
| Type: | Task | Priority: | Major - P3 |
| Reporter: | qaqz111 | Assignee: | Robert Stam |
| Resolution: | Done | Votes: | 0 |
| Labels: | Bug, double, float, json, question | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
.NetFX |
||
| Description |
output:
|
| Comments |
| Comment by qaqz111 [ 24/Apr/17 ] | ||||
|
Thanks for the explanation. Yes I did know the binary representation of floating numbers can not represent exactly the literal value of a number, what confused me is that this issue is new introduced in newer version driver. Then I checked github and saw the commit and the previous related issue CSHARP-1731. According to your words I understand now that the driver is preferred to serialize the exact binary data of a double. Previously I was preferring the consistency of input literal value and output json text, but I think I'm going to change a way to treat the data processing now. | ||||
| Comment by Robert Stam [ 24/Apr/17 ] | ||||
|
Double and float numbers in C# are binary, and they are unable to represent many decimal numbers accurately. This is not specifically related to the C# MongoDB Driver, it is inherent in the binary representation of double and float numbers. When you use a constant like "8.84" in your code the compiler converts it to the nearest possible equivalent binary double or float. When you later convert that back to a decimal number (by calling ToString) the binary double or float is converted back to decimal. Depending on the requested precision of the ToString conversion, the binary value might be rounded back to 8.84, but if you use a high enough precision you will see that the closest binary equivalent of 8.84 is not exactly 8.84. To see this in action try this code, which does not use the C# driver at all:
Output is:
| ||||
| Comment by qaqz111 [ 24/Apr/17 ] | ||||
|
Another code snippet:
output:
This is treated as double. And, the same issue with float:
output:
|