在 C# 中将 double 格式化为字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/355020/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:17:08  来源:igfitidea点击:

Formatting double as string in C#

c#.netformatting

提问by Guy

I have a Double which could have a value from around 0.000001 to 1,000,000,000.000

我有一个 Double,它的值可能在 0.000001 到 1,000,000,000.000 之间

I wish to format this number as a string but conditionally depending on its size. So if it's very small I want to format it with something like:

我希望将此数字格式化为字符串,但有条件地取决于其大小。因此,如果它非常小,我想使用以下格式对其进行格式化:

String.Format("{0:.000000000}", number);

if it's not that small, say 0.001 then I want to use something like

如果它不是那么小,比如说 0.001 那么我想使用类似的东西

String.Format("{0:.00000}", number);

and if it's over, say 1,000 then format it as:

如果它结束了,说 1,000 然后将其格式化为:

String.Format("{0:.0}", number);

Is there a clever way to construct this format string based on the size of the value I'm going to format?

有没有一种聪明的方法可以根据我要格式化的值的大小来构造这个格式字符串?

采纳答案by tvanfosson

Use Math.Log10 of the absolute value of the double to figure out how many 0's you need either left (if positive) or right (if negative) of the decimal place. Choose the format string based on this value. You'll need handle zero values separately.

使用 double 的绝对值的 Math.Log10 来计算小数点左边(如果为正)或右边(如果为负)需要多少个 0。根据此值选择格式字符串。您需要单独处理零值。

string s;
double epislon = 0.0000001; // or however near zero you want to consider as zero
if (Math.Abs(value) < epislon) {
    int digits = Math.Log10( Math.Abs( value ));
    // if (digits >= 0) ++digits; // if you care about the exact number
    if (digits < -5) {
       s = string.Format( "{0:0.000000000}", value );
    }
    else if (digits < 0) {
       s = string.Format( "{0:0.00000})", value );
    }
    else {
       s = string.Format( "{0:#,###,###,##0.000}", value );
    }
}
else {
    s = "0";
}

Or construct it dynamically based on the number of digits.

或者根据位数动态构造。

回答by Andrew Kennan

Use the # character for optional positions in the string:

将 # 字符用于字符串中的可选位置:

string.Format("{0:#,###,##0.000}", number);

I don't think you can control the number of decimal places like that as the precision of the double will likely mess things up.

我认为您无法控制这样的小数位数,因为 double 的精度可能会搞砸。

To encapsulate the logic of deciding how many decimal places to output you could look at creating a custom formatter.

要封装决定输出多少小数位的逻辑,您可以查看创建自定义格式化程序。

回答by Jonas Elfstr?m

The first two String.Format in your question can be solved by automatically removing trailing zeros:

您问题中的前两个 String.Format 可以通过自动删除尾随零来解决:

String.Format("{0:#,##0.########}", number);

And the last one you could solve by calling Math.Round(number,1) for values over 1000 and then use the same String.Format.

最后一个你可以通过调用 Math.Round(number,1) 来解决超过 1000 的值,然后使用相同的 String.Format。

Something like:

就像是:

String.Format("{0:#,##0.########}", number<1000 ? number : Math.Round(number,1));

回答by OwenP

If it were me, I'd write a custom wrapper class and put tvanfosson's code into its ToStringmethod. That way you could still work with the double value, but you'd get the right string representation in just about all cases. It'd look something like this:

如果是我,我会编写一个自定义包装类并将 tvanfosson 的代码放入其ToString方法中。这样您仍然可以使用 double 值,但您几乎在所有情况下都会获得正确的字符串表示形式。它看起来像这样:

class FormattedDouble
{ 
    public double Value { get; set; }

    protected overrides void ToString()
    {
        // tvanfosson's code to produce the right string
    }
}

Maybe it might be better to make it a struct, but I doubt it would make a big difference. You could use the class like this:

也许让它成为一个结构体可能会更好,但我怀疑它会产生很大的不同。你可以像这样使用这个类:

var myDouble = new FormattedDouble();
myDouble.Value = Math.Pi;
Console.WriteLine(myDouble);

回答by tophat02

Following up on OwenP's (and by "extension" tvanfosson):

跟进 OwenP 的(以及“扩展”tvanfosson):

If it's common enough, and you're on C# 3.0, I'd turn it into an extension method on the double:

如果它足够常见,并且您使用的是 C# 3.0,我会将其转换为 double 上的扩展方法:

class MyExtensions 
{
    public static string ToFormmatedString(this double d)
    {
        // Take d and implement tvanfosson's code
    }
}

Now anywhere you have a double you can do:

现在,您可以在任何地方进行双重操作:

double d = 1.005343;
string d_formatted = d.ToFormattedString();