Search code examples
c#sqlms-accessvbscript

C# Math.Round and nullable Doubles


I have taken on the task of converting a very old classic ASP/VBScript/Access web site to a "current" site. As you would suspect, most of it has been easier to just do-over, but there is a reporting page which relies on a bunch of calculations that aren't documented so I just have to use his code/formulas but move them to C#.

Just for full disclosure, I imported the Access database to SQL Server with no issues. I used EntityFramewok PowerTools (Code First) to reverse engineer the new database and create my .edmx file. I noticed that when EntityFramework created the .edmx for me, it defined fields that are floats in the database as nullable Doubles (Double?) in the C# class...is there any risk of transposing, chopping, or changing the value in any way when converting float to nullable double?

The other spot that I think is suspect is in the rounding. Obviously the math around rounding hasn't changed, but I wonder if VBScript and C# have any known differences in how they round.

So these lines in VBScript

varA1=oDataRs("boundData")
varB1i=varA1*3.0689
varB1=round(varB1i,3)

Becomes this is C#

var newVal = Math.Round(boundData.Value * 3.0689,3);

I am not converting anything to double or decimal, just working with it as it comes out of the database. I do have to use .Value though as I otherwise can't multiply a Double? and a Double.

The values are very close, but off by about .036 on a pretty important piece of data, and I can't find any reason why.


Solution

  • In fact, both .NET and VB use the Banker's Rounding algorithm, so you should get consistent results as long as you don't specify MidpointRounding.AwayFromZero.

    The really interesting question is whether the source data in the Access database is a floating-point number, or a Currency column. If it's Currency, then you should be using a decimal, not a double. That could cause small differences if the magnitudes of the numbers being multipled are sufficiently different.

    For the particularly important datum, what is the value of boundData?