.NET货币格式化程序:我可以指定使用银行家舍入吗?

5

有人知道我如何获取一个格式化字符串来使用银行家舍入吗?我一直在使用"{0:c}",但它没有像银行家舍入那样进行四舍五入。Math.Round()方法可以进行银行家舍入。我只需要能够使用格式化字符串来复制它的舍入方式。


注意:原问题有些误导性,提到正则表达式的回答也源于此。

{0:c}是什么样的正则表达式?在我看来更像是.NET格式字符串... - Shog9
只是出于好奇,为什么这需要一个正则表达式?使用现有的代码似乎更安全,因为它不太可能包含错误。 - Derek Park
什么是银行家舍入?如果有利于银行,则向上舍入,否则向下舍入? - Matthias Winkelmann
@MattW:银行家舍入法是解决那些在0.5上四舍五入的人的方法。0.5恰好处于0和1之间,它不靠近任何一个数。决定你总是要向上舍入会引入偏差(例如你支付的税款不应总是向上舍入-这就不公平了)。银行家舍入法设置为一半时间向上舍入,一半时间向下舍入,这样可以平衡一切。该算法始终朝偶数数字舍入。例如:0.5 -> 01.5 -> 22.5 -> 23.5 -> 44.5 -> 4 - Ian Boyd
5个回答

4

您是否可以直接在字符串输入上调用Math.Round()以获得所需的行为?

与其:

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

请做:

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

我相信这个功能解决了问题,但它增加了额外的麻烦和代码调用。我之前也遇到过这个问题,可以表达为:“是否有用于四舍五入的格式字符串?” - David J. Sokol
这种方法在只能提供格式字符串的情况下无法使用,例如在使用DisplayFormatAttribute时。 - Immortal Blue

3

0

不可能的,正则表达式没有“数字”的概念。你可以使用匹配评估器,但这会添加命令式的C#代码,并且会偏离你只需使用正则表达式的要求。


0

.Net内置支持算术和银行家舍入:

//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 );

"

即使"四舍五入其实是默认的,尽管在学校你学到的是"远离零"。

这是因为在计算机处理器底层也使用银行家舍入法。

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

我本以为任何四舍五入格式字符串都会默认使用银行家舍入法,这不是这种情况吗?


我们进行银行家舍入的原因是它(通常)可以给出更接近的结果 - 因为奇数和偶数通常相当均匀地分布,有时会取0.005美元,有时会给出0.005美元。我不确定CPU是否关心,但我们的会计师肯定会关心... - Mark Brackett
CPU正是出于这个原因而这样做的。这就是为什么ToEven是默认值 - 它消除了偏差(或者至少使其平衡)。这在浮点计算中非常有用,就像在银行业务中一样。 - Keith

0
如果您正在使用.NET 3.5,您可以定义一个扩展方法来帮助您完成这个操作:
public static class DoubleExtensions
{
    public static string Format(this double d)
    {
        return String.Format("{0:c}", Math.Round(d));
    }
}

然后,当你调用它时,你可以这样做:

12345.6789.Format();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接