title: Which currency rounding algorithm to use in .Net?
body: <p>Is there a best practice on which rounding algorithm to use in .Net for decimal currency rounding operations that takes into account back-end systems? Real world experience appreciated.</p>
  
  <hr>
  
  <p>.Net uses Banker’s Rounding by default.  (<strong>MidpointRounding.ToEven</strong>) This is at odds with the SQL Server back-end that I’ll be using because SQL Server uses arithmetic rounding (<strong>MidpointRounding.AwayFromZero</strong>) and has no built in function to mimic Banker's Rounding.</p>
  
  <p>Note: I'm using decimal(18, 4) in SQL Server, decimal in .Net</p>
  
  <p>Here's an example of .Net's default Banker's Rounding to two decimal places vs. SQL Server's rounding to two decimal places:</p>
  
  <pre><code>| Value | .Net  | SQL Server  |
  |-------|-------|-------------|
  | 2.445 | 2.44  | 2.45        |
  | 2.455 | 2.46  | 2.46        |
  | 2.465 | 2.46  | 2.47        |
  | 3.445 | 3.44  | 3.45        |
  | 3.455 | 3.46  | 3.46        |
  | 3.465 | 3.46  | 3.47        |
  
  // t-sql
  declare @decimalPlaces int
  set @decimalPlaces = 2
  
  select round(convert(decimal(18, 4), 2.445), @decimalPlaces) -- 2.45
  select round(convert(decimal(18, 4), 2.455), @decimalPlaces) -- 2.46
  select round(convert(decimal(18, 4), 2.465), @decimalPlaces) -- 2.47
  select round(convert(decimal(18, 4), 3.445), @decimalPlaces) -- 3.45
  select round(convert(decimal(18, 4), 3.455), @decimalPlaces) -- 3.46
  select round(convert(decimal(18, 4), 3.465), @decimalPlaces) -- 3.47
  
  // .Net
  var algorithm = MidpointRounding.ToEven;
  var decimalPlaces = 2;
  Console.WriteLine(decimal.Round(2.445M, decimalPlaces, algorithm).ToString()); // 2.44
  Console.WriteLine(decimal.Round(2.455M, decimalPlaces, algorithm).ToString()); // 2.46
  Console.WriteLine(decimal.Round(2.465M, decimalPlaces, algorithm).ToString()); // 2.46
  Console.WriteLine(decimal.Round(3.445M, decimalPlaces, algorithm).ToString()); // 3.44
  Console.WriteLine(decimal.Round(3.455M, decimalPlaces, algorithm).ToString()); // 3.46
  Console.WriteLine(decimal.Round(3.465M, decimalPlaces, algorithm).ToString()); // 3.46
  </code></pre>
  
  <p>If I ever retrieve a value from SQL Server and let it handle the rounding I'll wind up with pennies off here and there as compared to what .Net were to tell me because of it's default Banker's Rounding.</p>
  
  <p>It seems that I should forge ahead and use arithmetic rounding throughout my .Net code base but I see an open source project (<a href="http://www.nopcommerce.com/downloads.aspx" rel="nofollow">nopCommerce</a>) using the default Banker's Rounding so it makes me wonder what the best approach is.</p>
  
  <hr>
  
  <p>Perhaps a better question is: Is there any reason <strong>not</strong> to use arithmetic rounding (<strong>MidpointRounding.AwayFromZero</strong>) for currencies in .Net?</p>