2 <clause number="11.1.5" title="Floating point types">
3 <paragraph>C# supports two floating-point types: <keyword>float</keyword> and <keyword>double</keyword>. The <keyword>float</keyword> and <keyword>double</keyword> types are represented using the 32-bit single-precision and 64-bit double-precision IEEE 754 formats, which provide the following sets of values: <list><list_item> Positive zero and negative zero. In most situations, positive zero and negative zero behave identically as the simple value zero, but certain operations distinguish between the two (<hyperlink>14.7.2</hyperlink>). </list_item><list_item> Positive infinity and negative infinity. Infinities are produced by such operations as dividing a non-zero number by zero. <example>[Example: For example, 1.0 / 0.0 yields positive infinity, and -1.0 / 0.0 yields negative infinity. end example]</example> </list_item><list_item> The Not-a-Number value, often abbreviated NaN. NaNs are produced by invalid floating-point operations, such as dividing zero by zero. </list_item><list_item> The finite set of non-zero values of the form s <unicode>215</unicode> m <unicode>215</unicode> 2<super>e</super>, where s is 1 or <unicode>8722</unicode>1, and m and e are determined by the particular floating-point type: For <keyword>float</keyword>, 0 < m < 2<super>24</super> and <unicode>8722</unicode>149 <unicode>8804</unicode> e <unicode>8804</unicode> 104, and for <keyword>double</keyword>, 0 < m < 2<super>53</super> and <unicode>8722</unicode>1075 <unicode>8804</unicode> e <unicode>8804</unicode> 970. Denormalized floating-point numbers are considered valid non-zero values. </list_item></list></paragraph>
4 <paragraph>The <keyword>float</keyword> type can represent values ranging from approximately 1.5 <unicode>215</unicode> 10<super>-45</super> to 3.4 <unicode>215</unicode> 10<super>38</super> with a precision of 7 digits. </paragraph>
5 <paragraph>The <keyword>double</keyword> type can represent values ranging from approximately 5.0 <unicode>215</unicode> 10<super>-324</super> to 1.7 <unicode>215</unicode> 10<super>308</super> with a precision of 15-16 digits. </paragraph>
6 <paragraph>If one of the operands of a binary operator is of a floating-point type, then the other operand must be of an integral type or a floating-point type, and the operation is evaluated as follows: <list><list_item> If one of the operands is of an integral type, then that operand is converted to the floating-point type of the other operand. </list_item><list_item> Then, if either of the operands is of type <keyword>double</keyword>, the other operand is converted to <keyword>double</keyword>, the operation is performed using at least <keyword>double</keyword> range and precision, and the type of the result is <keyword>double</keyword> (or <keyword>bool</keyword> for the relational operators). </list_item><list_item> Otherwise, the operation is performed using at least <keyword>float</keyword> range and precision, and the type of the result is <keyword>float</keyword> (or <keyword>bool</keyword> for the relational operators). </list_item></list></paragraph>
7 <paragraph>The floating-point operators, including the assignment operators, never produce exceptions. Instead, in exceptional situations, floating-point operations produce zero, infinity, or NaN, as described below: <list><list_item> If the result of a floating-point operation is too small for the destination format, the result of the operation becomes positive zero or negative zero. </list_item><list_item> If the result of a floating-point operation is too large for the destination format, the result of the operation becomes positive infinity or negative infinity. </list_item><list_item> If a floating-point operation is invalid, the result of the operation becomes NaN. </list_item><list_item> If one or both operands of a floating-point operation is NaN, the result of the operation becomes NaN. </list_item></list></paragraph>
8 <paragraph>Floating-point operations may be performed with higher precision than the result type of the operation. <example>[Example: For example, some hardware architectures support an "extended" or "long double" floating-point type with greater range and precision than the <keyword>double</keyword> type, and implicitly perform all floating-point operations using this higher precision type. Only at excessive cost in performance can such hardware architectures be made to perform floating-point operations with less precision, and rather than require an implementation to forfeit both performance and precision, C# allows a higher precision type to be used for all floating-point operations. Other than delivering more precise results, this rarely has any measurable effects. However, in expressions of the form x * y / z, where the multiplication produces a result that is outside the <keyword>double</keyword> range, but the subsequent division brings the temporary result back into the <keyword>double</keyword> range, the fact that the expression is evaluated in a higher range format may cause a finite result to be produced instead of an infinity. end example]</example> </paragraph>