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:
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:
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
This discovery on how Math.floor is implemented is quite weird. It does look like a bug on Microsoft's side, this is
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.Length>2) Console.WriteLine(ss + "." + ss.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.
More from @sqldibia