"Could someone let me know the algorithm it uses to compute the rounding?"

Math.Round(x, 2) is the same as Math.Round(x * 100.0) / 100.0.

The source of the "problem" is that 100.0 which increases errors introduced by the fact that some floating point number that appear to have exact representation in base 10 do not have a equivalent representation in base 2. The following code should clear
up thing:

foreach (var d in new[] { 7.955, 8.955, 12.955, 15.955, 16.955, 17.955, 18.955, 20.955, 27.955 })
Console.WriteLine("{0:r} {1:r} {2:r}", d, d * 100.0, Math.Round(d * 100.0) / 100.0);

Note how 16.955 becomes 1695.49999... rather than 1695.5. This otherwise very small error (something like 0.0000000000001) is then blown out by rounding and ends up as a 0.01 error.

In general you should not expect "exact" results when using float/double. If those values represent currency (they look a bit like prices to me) then you should use decimal instead.