0

C# Math.Floor and Math.Round Gives Different Values for Negative and Positive Parameters

Emeka OkekeJun 18, 2020

Understanding this potential pitfall when using C#'s Math.floor method is very important. As a mistake could be very costly to the organization's data.

Recently while developing an ETL application with SSIS and C# for a client, I found myself almost questioning my basic arithmetic skills.

I was intially test-running and debugging my code snippet on dotnetfiddle.net when I found myself stuck on the unexpected results the Math.floor method yielded. We found that C#'s Math.floor method was giving diiferent values for negative and positive decimal values.

The client's requirement was to round the decimal money values to a penny. So I thought doing this:


Math.Floor(93.275*100) /100.00 

would yield 93.27, instead I got 93.28. I initially thought this is a problem with dotnetfiddle.net, because my colleage was also debugging the issue on his visual studio and was getting 93.27 value, the expected result, while my code was returning 93.27 value.

I and my colleague went back and fort with this, we even argued over it. He suggested that I try the (decimal) /100M version in:


Math.Floor(93.275*100) /100M 

but I got the same result. I broke down the chained method calls into statements, and put breakpoints so this way I can better track down the issue to the specific statement that might be causing the issue. This was how I tracked the issue to Math.floor which was yielding the same unexpected result.

Eventually I found that the issue is with the signed decimal value. With breakpoints, I found that the value that my code was feeding into Math.floor has a negative sign. So when Math.Floor(93.275*100), the result is 93.27, but when Math.Floor(-93.275*100), the result is -93.28.

This discovery on how Math.floor is implemented is quite weird. It does look like a bug on Microsoft's side, this is .NET 4.7.2.

I verified with the business analyst, and she confirmed that they really wanted two decimal places in place without any rounding. So I ended up ditching Math.floor entirely and simply used string like this:


string s = "93.275";
        string[] ss = s.Split('.');
       
        if(ss[1].Length>2)           
            Console.WriteLine(ss[0] + "." + ss[1].Substring(0,2));
        else
            Console.WriteLine(s);

Have you encountered this issue before? if yes, how did you resolve it? Do you have any questions on my workaround or do you have any suggestions on a better alternative solution? Please let us know in the comment section below.I wrote this post to give you .NET developer a heads-up on this so as to avoid this in your codes.

Emeka Okeke@sqldibia+ Follow
0
Emeka Okeke+ Follow
locationPennsburg, PennsylvaniajoinedDec 11, 2019

More from @sqldibia