在 C# 中实现复杂数字格式的最佳方法

发布于 2024-11-09 03:37:28 字数 1365 浏览 0 评论 0原文

在 C# 中复制此类行为的最佳方法是什么?

// Converts decimal to a 0-padded string with minimum specified width and precision.
sprintf(out, "%0*.*lf", width, precision, decimal);

我读过标准自定义复合 格式字符串,但我看不到任何好的方法来实现这一点。

我问的原因是,我刚刚在我维护的一些代码中遇到了这个丑陋的代码片段,我们需要根据外部接口指定的可变宽度和精度来格式化一堆小数:

private static String ZEROS = "00000000000000000000000000";

public override string Format(decimal input, int width, int precision)
{
    String formatString = ZEROS.Substring(0, width - precision - 1) 
                          + "." + ZEROS.Substring(0, precision);
    return ToDecimal(input).ToString(formatString);
}

我想将其替换为有些不那么可怕。

更新

由于最终答案隐藏在评论中,因此如下:

public override string Format(decimal input, int width, int precision)
{
    string.Format("{0," + width + ":F" + precision + "}", input).Replace(" ","0");
}

在我的情况下,输入始终为正,因此这也有效:

public override string Format(decimal input, int width, int precision)
{
    return input.ToString("F"+precision).PadLeft(width, 0);
}

What is the best way to replicate the behaviour of something like this in C#?

// Converts decimal to a 0-padded string with minimum specified width and precision.
sprintf(out, "%0*.*lf", width, precision, decimal);

I had a read of standard, custom and composite format strings, but I can't see any nice way to achieve this.

The reason I ask is that I just came across this ugly snippet in some code I am maintaining where we are required to format a bunch of decimals according to variable widths and precisions as specified by an external interface:

private static String ZEROS = "00000000000000000000000000";

public override string Format(decimal input, int width, int precision)
{
    String formatString = ZEROS.Substring(0, width - precision - 1) 
                          + "." + ZEROS.Substring(0, precision);
    return ToDecimal(input).ToString(formatString);
}

and I would like to replace it with someing a little less horrendous.

UPDATE

Since the final answer is buried in comments, here it is:

public override string Format(decimal input, int width, int precision)
{
    string.Format("{0," + width + ":F" + precision + "}", input).Replace(" ","0");
}

In my case the input is always positive so this works too:

public override string Format(decimal input, int width, int precision)
{
    return input.ToString("F"+precision).PadLeft(width, 0);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

只是在用心讲痛 2024-11-16 03:37:28

您可以这样写,生成一个标准格式字符串,然后使用它:

public static string Format(decimal input, int width, int precision)
{
    var format = string.Format("{{0,{0}:F{1}}}", width, precision);
    // generates (e.g. width=15, precision=5)  "{0,15:F5}"
    // then format using this and replace padding with zeroes
    return string.Format(format, input).Replace(" ", "0");
}

或者不调用 format 两次,只需连接格式字符串,具体取决于您的偏好:

string.Format("{0," + width + ":F" + precision + "}", input).Replace(" ","0")

您必须随后替换空格,因为无法指定填充字符。或者,您可以编写自己的格式化程序来填充特定字符。但这是有效的:)

编辑:这与所有输入的原始内容匹配,除了精度= 0时除外。在这种情况下,原始版本是不正确的,因为即使小数点不存在,它也会将小数点计为宽度的一部分。

糟糕:忘记检查负数。

这是一个更简单的版本,但必须检查数字是否为负数才能正确填充:

public override string Format(decimal input, int width, int precision)
{
    var output = input.ToString("F" + precision);
    return input < 0
        ? "-" + output.Substring(1).PadLeft(width, '0')
        :       output             .PadLeft(width, '0');
}

You could write it like this, generating a standard format string and then using it:

public static string Format(decimal input, int width, int precision)
{
    var format = string.Format("{{0,{0}:F{1}}}", width, precision);
    // generates (e.g. width=15, precision=5)  "{0,15:F5}"
    // then format using this and replace padding with zeroes
    return string.Format(format, input).Replace(" ", "0");
}

Or instead of calling format twice just concat the format string, depending on your preference:

string.Format("{0," + width + ":F" + precision + "}", input).Replace(" ","0")

You have to replace the spaces afterwards since there's no way to specify the padding character. Alternately you could write your own formatter to pad with a specific character. This works though :)

Edit: This matches the original for all inputs except when precision = 0. In that case, the original is incorrect, since it counts the decimal point as part of the width even when it isn't present.

Oops: Forgot to check negative numbers.

Here is a simpler version, but have to check if the number is negative to get the padding correct:

public override string Format(decimal input, int width, int precision)
{
    var output = input.ToString("F" + precision);
    return input < 0
        ? "-" + output.Substring(1).PadLeft(width, '0')
        :       output             .PadLeft(width, '0');
}
一个人的旅程 2024-11-16 03:37:28

像这样的东西:

return input.ToString(new string('0', width) + '.' + new string('0', precision));

编辑:实际上,这是一个更好的:

return input.ToString(new string('0', width - 1).insert(width - precision, '.'));

Something like this:

return input.ToString(new string('0', width) + '.' + new string('0', precision));

?

Edit: acutally, here's a better one:

return input.ToString(new string('0', width - 1).insert(width - precision, '.'));
油焖大侠 2024-11-16 03:37:28

好吧,摆脱ZERO的一种方法是

public override string Format(decimal input, int width, int precision)
{
    String formatString = new string('0', width - precision - 1) 
                      + "." + new string('0', precision);
    return ToDecimal(input).ToString(formatString);
}

不确定你是否还能做很多其他事情。

Well, one way to get rid of the ZERO would be

public override string Format(decimal input, int width, int precision)
{
    String formatString = new string('0', width - precision - 1) 
                      + "." + new string('0', precision);
    return ToDecimal(input).ToString(formatString);
}

Not sure if you can do much else.

毁梦 2024-11-16 03:37:28

这已经是最好的了:

public static string double2string( double value , int integerDigits , int fractionalDigits )
{
  string        decimalPoint = CultureInfo.CurrentUICulture.NumberFormat.NumberDecimalSeparator ;
  StringBuilder sb           = new StringBuilder() ;

  sb.Append('0',integerDigits)
    .Append(decimalPoint)
    .Append('0',fractionalDigits)
    ;
  return value.ToString( sb.ToString() ) ;
}

This is about as good as it gets:

public static string double2string( double value , int integerDigits , int fractionalDigits )
{
  string        decimalPoint = CultureInfo.CurrentUICulture.NumberFormat.NumberDecimalSeparator ;
  StringBuilder sb           = new StringBuilder() ;

  sb.Append('0',integerDigits)
    .Append(decimalPoint)
    .Append('0',fractionalDigits)
    ;
  return value.ToString( sb.ToString() ) ;
}
断桥再见 2024-11-16 03:37:28

我相信您可以调用 Decimal.ToString 并向其传递一个您可以生成的自定义数字格式字符串

I beleive you could just call Decimal.ToString and pass it a Custom Numeric Format String that you can generate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文