<!-- 
RSS generated by JIRA (9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66) at Wed Feb 07 21:38:31 UTC 2024

It is possible to restrict the fields that are returned in this document by specifying the 'field' parameter in your request.
For example, to request only the issue key and summary append 'field=key&field=summary' to the URL of your request.
-->
<rss version="0.92" >
<channel>
    <title>MongoDB Jira</title>
    <link>https://jira.mongodb.org</link>
    <description>This file is an XML representation of an issue</description>
    <language>en-us</language>    <build-info>
        <version>9.7.1</version>
        <build-number>970001</build-number>
        <build-date>13-04-2023</build-date>
    </build-info>


<item>
            <title>[CSHARP-1047] Losing precision in conversion from float to BsonDouble</title>
                <link>https://jira.mongodb.org/browse/CSHARP-1047</link>
                <project id="10041" key="CSHARP">C# Driver</project>
                    <description>&lt;p&gt;We could improve the BsonDouble type converting values from a float type without losing precision like decimal types (decimal type in C# solves the losing precision converting some numeric values).&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;With the actual implementation, the function BsonTypeMapper.MapToBsonValue returns a BsonDouble with precision lost if the parameter passed is a float. See the following new test case:&lt;/p&gt;

&lt;p&gt;float value2 = 1.3f;&lt;br/&gt;
BsonDouble secondBsonValue = (BsonDouble)BsonTypeMapper.MapToBsonValue(value2);&lt;br/&gt;
BsonDouble expectedResult = 1.3d;&lt;br/&gt;
Assert.AreSame(expectedResult, secondBsonValue);&lt;/p&gt;

&lt;p&gt;The test case result is: &lt;/p&gt;

&lt;p&gt;MongoDB.Bson.Tests.BsonTypeMapperTests.TestMapBsonDouble:&lt;/p&gt;

&lt;p&gt;  Expected: same as &amp;lt;1.3&amp;gt;&lt;/p&gt;

&lt;p&gt;  But was:  &amp;lt;1.2999999523162842&amp;gt;&lt;/p&gt;

&lt;p&gt;Also the comparison is not entirely accurate. See the following code of a console test code:&lt;/p&gt;

&lt;p&gt;float value = 1.3f;&lt;br/&gt;
var bsonValue = (BsonDouble)BsonTypeMapper.MapToBsonValue(value);&lt;br/&gt;
bool result1 = (value == bsonValue);&lt;br/&gt;
Console.WriteLine(&quot;Case 1: Original: &lt;/p&gt;
{0}, converted: {1}. AreSame: {2}. &#191;?&#191;&quot;, value, bsonValue, result1);&lt;br/&gt;
var bsonDouble = (BsonDouble)BsonTypeMapper.MapToBsonValue(value, BsonType.Double);&lt;br/&gt;
bool result2 = (value == bsonDouble);&lt;br/&gt;
Console.WriteLine(&quot;Case 2: Original: {0}
&lt;p&gt;, converted: &lt;/p&gt;
{1}. AreSame: {2}. &#191;?&#191; &quot;, value, bsonDouble, result2);&lt;br/&gt;
Console.ReadKey();&lt;br/&gt;
&lt;br/&gt;
Outputs:&lt;br/&gt;
&lt;br/&gt;
Case 1: Original: 1,3, converted: 1.2999999523162842. AreSame: True. &#191;?&#191;&lt;br/&gt;
Case 2: Original: 1,3, converted: 1.2999999523162842. AreSame: True. &#191;?&#191;&lt;br/&gt;
&lt;br/&gt;
Proposed solution:&lt;br/&gt;
&lt;br/&gt;
Use the decimal type as an intermediate cast.&lt;br/&gt;
&lt;br/&gt;
This code converts values without losing precision.&lt;br/&gt;
&lt;br/&gt;
float f = 3.2f;&lt;br/&gt;
double d = (double)(decimal)f;&lt;br/&gt;
double d2 = (double)f; // Loss&lt;br/&gt;
Console.WriteLine(&quot;Original float: {0} and converted double: {1}
&lt;p&gt;&quot;, f, d);&lt;br/&gt;
Console.WriteLine(&quot;Original float: &lt;/p&gt;
{0}
&lt;p&gt; and converted double without intermediate decimal: &lt;/p&gt;
{1}
&lt;p&gt;&quot;, f, d2);&lt;/p&gt;

&lt;p&gt;Output:&lt;br/&gt;
Original float: 3,2 and converted double: 3,2&lt;br/&gt;
Original float: 3,2 and converted double without intermediate decimal: 3,2000000&lt;br/&gt;
4768372&lt;/p&gt;

&lt;p&gt;I needed solve it and I have a valid implementation which passes the test cases and I&#8217;m able to pull request shortly.&lt;/p&gt;</description>
                <environment></environment>
        <key id="154121">CSHARP-1047</key>
            <summary>Losing precision in conversion from float to BsonDouble</summary>
                <type id="4" iconUrl="https://jira.mongodb.org/secure/viewavatar?size=xsmall&amp;avatarId=14710&amp;avatarType=issuetype">Improvement</type>
                                            <priority id="4" iconUrl="https://jira.mongodb.org/images/icons/priorities/minor.svg">Minor - P4</priority>
                        <status id="6" iconUrl="https://jira.mongodb.org/images/icons/statuses/closed.png" description="The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.">Closed</status>
                    <statusCategory id="3" key="done" colorName="success"/>
                                    <resolution id="9">Done</resolution>
                                        <assignee username="robert@mongodb.com">Robert Stam</assignee>
                                    <reporter username="MarkCBB">Marc Cortada</reporter>
                        <labels>
                            <label>bson</label>
                    </labels>
                <created>Thu, 21 Aug 2014 18:56:05 +0000</created>
                <updated>Mon, 22 Sep 2014 22:08:51 +0000</updated>
                            <resolved>Mon, 22 Sep 2014 19:11:12 +0000</resolved>
                                                                    <component>BSON</component>
                                        <votes>0</votes>
                                    <watches>1</watches>
                                                                                                                <comments>
                            <comment id="724554" author="markcbb" created="Mon, 22 Sep 2014 22:08:51 +0000"  >&lt;p&gt;Thank you Robert for the detailed explanation and lesson &lt;img class=&quot;emoticon&quot; src=&quot;https://jira.mongodb.org/images/icons/emoticons/wink.png&quot; height=&quot;16&quot; width=&quot;16&quot; align=&quot;absmiddle&quot; alt=&quot;&quot; border=&quot;0&quot;/&gt; . You are right: it&apos;s a reflection, not a loss of precision.&lt;br/&gt;
I&apos;ll close the pull request in Git.&lt;/p&gt;</comment>
                            <comment id="724373" author="rstam" created="Mon, 22 Sep 2014 19:10:50 +0000"  >&lt;p&gt;The behavior you are observing is NOT a loss of precision, but rather just a reflection of the fact that base-2 floating point numbers can&apos;t accurately represent decimal fractions.&lt;/p&gt;

&lt;p&gt;The C# driver converts float to BsonDouble with NO loss of precision, which is true simply because the C# language (or rather, the representation of 32-bit and 64-bit floating point numbers) guarantees that floats can be converted to doubles with no loss of precision.&lt;/p&gt;

&lt;p&gt;Consider the following sample code:&lt;/p&gt;

&lt;p/&gt;
&lt;div id=&quot;syntaxplugin&quot; class=&quot;syntaxplugin&quot; style=&quot;border: 1px dashed #bbb; border-radius: 5px !important; overflow: auto; max-height: 30em;&quot;&gt;
&lt;table cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; border=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size: 1em; line-height: 1.4em !important; font-weight: normal; font-style: normal; color: black;&quot;&gt;
		&lt;tbody &gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;  margin-top: 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;float f = 1.3f;&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;BsonDouble x = (BsonDouble)BsonTypeMapper.MapToBsonValue(f); // NO loss of precision&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;BsonDouble y = (BsonDouble)BsonTypeMapper.MapToBsonValue(1.3d); // 1.3d is NOT the same number as 1.3f&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;BsonDouble z = (BsonDouble)BsonTypeMapper.MapToBsonValue((double)(decimal)f); // two rounding errors&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&amp;nbsp;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;Console.WriteLine(&quot;f == x.Value is {0}&quot;, f == x.Value);&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;Console.WriteLine(&quot;f == y.Value is {0}&quot;, f == y.Value);&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;Console.WriteLine(&quot;f == z.Value is {0}&quot;, f == z.Value);&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   margin-bottom: 10px;  width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;Console.WriteLine(&quot;1.3f == 1.3d is {0}&quot;, 1.3f == 1.3d);&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
			&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p/&gt;

&lt;p&gt;which outputs:&lt;/p&gt;

&lt;p/&gt;
&lt;div id=&quot;syntaxplugin&quot; class=&quot;syntaxplugin&quot; style=&quot;border: 1px dashed #bbb; border-radius: 5px !important; overflow: auto; max-height: 30em;&quot;&gt;
&lt;table cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; border=&quot;0&quot; width=&quot;100%&quot; style=&quot;font-size: 1em; line-height: 1.4em !important; font-weight: normal; font-style: normal; color: black;&quot;&gt;
		&lt;tbody &gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;  margin-top: 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;f == x.Value is True&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;f == y.Value is False&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;f == z.Value is False&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
				&lt;tr id=&quot;syntaxplugin_code_and_gutter&quot;&gt;
						&lt;td  style=&quot; line-height: 1.4em !important; padding: 0em; vertical-align: top;&quot;&gt;
					&lt;pre style=&quot;font-size: 1em; margin: 0 10px;   margin-bottom: 10px;  width: auto; padding: 0;&quot;&gt;&lt;span style=&quot;color: black; font-family: &apos;Consolas&apos;, &apos;Bitstream Vera Sans Mono&apos;, &apos;Courier New&apos;, Courier, monospace !important;&quot;&gt;1.3f == 1.3d is False&lt;/span&gt;&lt;/pre&gt;
			&lt;/td&gt;
		&lt;/tr&gt;
			&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p/&gt;

&lt;p&gt;The first result is True precisely because a float can be converted to a BsonDouble with NO loss of precision.&lt;/p&gt;

&lt;p&gt;The second result is False because 1.3d is NOT the same number as 1.3f. Neither constant is exactly equal to 1.3, because 1.3 does not have an exact representation in base-2 floating point numbers. The reason they are NOT the same value is that 1.3d is represented using 64 bits, while 1.3f is represented using 32 bits. So 1.3d is a closer approximation to the decimal number 1.3 than 1.3f is, and therefore is not the same value.&lt;/p&gt;

&lt;p&gt;The third result is False because converting from float to decimal and then to double doesn&apos;t actually accomplish what you intend, or rather, while it might accomplish what you want in one example, it is the wrong thing to do in general because the end result is not the same number you started out with. When you convert from float to decimal you introduce rounding errors as binary fractions are converted to decimal, and when you convert from decimal to double you introduce a second set of rounding errors.&lt;/p&gt;

&lt;p&gt;The final result is False just to illustrate that the compiler agrees with me that 1.3f and 1.3d are not the same number.&lt;/p&gt;

&lt;p&gt;I&apos;m going to close this ticket as &quot;Works as Designed&quot;.&lt;/p&gt;</comment>
                            <comment id="702476" author="craiggwilson" created="Mon, 25 Aug 2014 13:43:53 +0000"  >&lt;p&gt;Thanks Marc. We are discussing the implications of doing this and will get back to you.&lt;/p&gt;</comment>
                            <comment id="702305" author="markcbb" created="Mon, 25 Aug 2014 09:51:12 +0000"  >&lt;p&gt;Pull request is done!&lt;br/&gt;
&lt;a href=&quot;https://github.com/mongodb/mongo-csharp-driver/pull/188&quot; class=&quot;external-link&quot; target=&quot;_blank&quot; rel=&quot;nofollow noopener&quot;&gt;https://github.com/mongodb/mongo-csharp-driver/pull/188&lt;/a&gt;&lt;/p&gt;</comment>
                    </comments>
                    <attachments>
                    </attachments>
                <subtasks>
                    </subtasks>
                <customfields>
                                                                                                                                                                                                                        <customfield id="customfield_10011" key="com.atlassian.jira.plugin.system.customfieldtypes:radiobuttons">
                        <customfieldname>Backwards Compatibility</customfieldname>
                        <customfieldvalues>
                                <customfieldvalue key="10038"><![CDATA[Fully Compatible]]></customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                <customfield id="customfield_15850" key="com.atlassian.jira.plugins.jira-development-integration-plugin:devsummary">
                        <customfieldname>Development</customfieldname>
                        <customfieldvalues>
                            
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    <customfield id="customfield_12550" key="com.pyxis.greenhopper.jira:gh-lexo-rank">
                        <customfieldname>Rank</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>2|hs1l0n:</customfieldvalue>

                        </customfieldvalues>
                    </customfield>
                                                                <customfield id="customfield_10558" key="com.pyxis.greenhopper.jira:gh-global-rank">
                        <customfieldname>Rank (Obsolete)</customfieldname>
                        <customfieldvalues>
                            <customfieldvalue>133825</customfieldvalue>
                        </customfieldvalues>
                    </customfield>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            </customfields>
    </item>
</channel>
</rss>