5

Does anyone know how I can get a format string to use bankers rounding? I have been using "{0:c}" but that doesn't round the same way that bankers rounding does. The Math.Round() method does bankers rounding. I just need to be able to duplicate how it rounds using a format string.


Note: the original question was rather misleading, and answers mentioning regex derive from that.

Shog9
  • 156,901
  • 35
  • 231
  • 235
user21767
  • 95
  • 5
  • What sort of a regex is {0:c}? Looks more like a .NET format string to me... – Shog9 Sep 24 '08 at 17:18
  • Just out of curiosity, why does this need to be a regular expression? It seems that using the existing code would be safer, as it's less likely to contain bugs. – Derek Park Sep 24 '08 at 17:19
  • what's banker's rounding? Up if in the bank's favor, down otherwise? – Matthias Winkelmann Sep 24 '08 at 17:25
  • @MattW: Banker's Rounding is the cure for people who round up on `0.5`. `0.5` is exactly half-way between 0 and 1, it's not closer to either. Deciding you're *always* going to round **up** is introducing a bias (e.g. the tax you pay shouldn't always be rounded up - that's just not fair). Banker's Rounding is setup so that half the time you round up, and half the time you round down, this evens things out. The algorithm is always round towards the *even* digit. e.g.: `0.5 -> 0`, `1.5 -> 2`, `2.5 -> 2`, `3.5 -> 4`, `4.5 -> 4` – Ian Boyd Sep 09 '11 at 13:56

5 Answers5

4

Can't you simply call Math.Round() on the string input to get the behavior you want?

Instead of:

string s = string.Format("{0:c}", 12345.6789);

Do:

string s = string.Format("{0:c}", Math.Round(12345.6789));
Zach Lute
  • 601
  • 1
  • 5
  • 9
  • I'm sure that this functionality solves the problem, but it adds extra headache and code calling. I've experienced this problem before as well, which I guess could be expressed as: "Are there format strings for rounding?: – David J. Sokol Sep 24 '08 at 17:34
  • This doesn't work in scenarios where you can only provide the format string, such as when using a DisplayFormatAttribute – Immortal Blue Jul 10 '15 at 11:22
3

Regexp is a pattern matching language. You can't do arithmetic operations in Regexp.

Do some experiements with IFormatProvider and ICustomFormatter. Here is a link might point you in the right direction. http://codebetter.com/blogs/david.hayden/archive/2006/03/12/140732.aspx

jop
  • 82,837
  • 10
  • 55
  • 52
0

Its not possible, a regular expression doesn't have any concept of "numbers". You could use a match evaluator but you'd be adding imperative c# code, and would stray from your regex only requirement.

viggity
  • 15,039
  • 7
  • 88
  • 96
0

.Net has built in support for both Arithmetic and Bankers' rounding:

//midpoint always goes 'up': 2.5 -> 3
Math.Round( input, MidpointRounding.AwayFromZero );

//midpoint always goes to nearest even: 2.5 -> 2, 5.5 -> 6
//aka bankers' rounding
Math.Round( input, MidpointRounding.ToEven );

"To even" rounding is actually the default, even though "away from zero" is what you learnt at school.

This is because under the hood computer processors also do bankers' rounding.

//defaults to banker's
Math.Round( input );

I would have thought that any rounding format string would default to bankers' rounding, is this not the case?

Keith
  • 150,284
  • 78
  • 298
  • 434
  • The reason we do banker's rounding is that it (normally) gives a closer result - since odds and evens are usually fairly uniformly distributed, you'll sometimes be taking $0.005 and sometimes giving $0.005. I'm not sure that CPU's care either way, but our accountants sure do.... – Mark Brackett Sep 24 '08 at 20:54
  • The CPUs do - for precisely that reason. That's why ToEven is the default - it eliminates bias (or at least evens it out). This is useful in floating point calculations, just as it is in banking. – Keith Sep 26 '08 at 07:35
0

If you are using .NET 3.5, you can define an extension method to help you do this:

public static class DoubleExtensions
{
    public static string Format(this double d)
    {
        return String.Format("{0:c}", Math.Round(d));
    }
}

Then, when you call it, you can do:

12345.6789.Format();
Abe Heidebrecht
  • 30,090
  • 7
  • 62
  • 66