Why does Math.Floor return a double?


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Someone recently asked me why
Math.Floor return a double? I chatted with some folks on the team and got this
response. "urn:schemas-microsoft-com:office:office" />


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">You could ask the same question
about Sin, Log and all the other things on Math: they all take and return Double
and are subject to the same precision issues.


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Admittedly, Math.Floor is a little
weird, because it returns a whole integer. However, it can't return any normal
integer, because Int64 can't cover the full range of Double. The only return
value that would make more sense would be Decimal.


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">You could make a reasonable case
that there should be Decimal versions of most or all of the methods on Math. We
should probably consider that a reasonable end-point for the long term evolution
of this class.


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="MARGIN: 0in 0in 0pt; mso-layout-grid-align: none"> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">We are of course looking at adding
more overloads in the future.


 

Comments (4)

  1. Jakub Skopal says:

    Conversion to System.Decimal would have the same problem as conversion into System.Int32/System.Int64.
    There’s no guarantee, that the resulting value would fit. Consider:

    double dblNumber = 1E200;
    decimal decNumber = (decimal)Math.Floor(dblNumber);
    // Unhandled Exception: System.OverflowException: Value was either too large or too small for a Decimal.

    According to niceness rules of Microsoft.NET Framework, one should not create any implicit conversion operators when there’s an opportunity for the convertee not to fit into destination variable. Forcing programmer to explicitly state, that s/he wants to convert the destination value into int or decimal also forces him to think: "oops, does the resulting value ALWAYS fit into my new variable"?

    (niceness rules taken out of http://msdn.microsoft.com/library/default.asp?url=/library/en-us/csref/html/vclrfexplicit.asp)

  2. Yonathan Lavi says:

    double floor(double x) for a double x greater than 2^M where M = size of double’s mantissa in bits = 52 returns an invalid result, exactly because the return value is double. At this point the absolute difference between two subsequent doubles becomes greater than 1, so the correct result can’t even be correctly represented by a double. I find it curious people then complain about 64-bit integers being unable to handle values over 2^63. Also, CPUs have instructions that round doubles to integers. The implementation of floor often needs to convert that integer back to double and then you often convert back to integer in your own program (that’s the most common use for floor, I think… stuff like int(floor(x)) ). The whole process is inefficient, less accurate and has no concievable benefits.

Skip to main content