我有一个Double,其值可以从0.000001到1,000,000,000.000
我希望将此数字格式化为字符串,但有条件地取决于其大小。因此,如果它非常小,我想用以下内容对其进行格式化:
String.Format("{0:.000000000}", number);
如果不是那么小,比如0.001,那么我想使用像
这样的东西String.Format("{0:.00000}", number);
如果结束了,请说1000,然后将其格式化为:
String.Format("{0:.0}", number);
根据我要格式化的值的大小,是否有一种聪明的方法来构造这个格式字符串?
答案 0 :(得分:15)
使用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";
}
或者根据位数动态构建它。
答案 1 :(得分:2)
在字符串中使用#字符作为可选位置:
string.Format("{0:#,###,##0.000}", number);
我认为你不能控制像这样的小数位数,因为双精度的精确度可能会搞砸。
要封装决定输出多少小数位的逻辑,您可以查看创建自定义格式化程序。
答案 2 :(得分:2)
你问题中的前两个String.Format可以通过自动删除尾随零来解决:
String.Format("{0:#,##0.########}", number);
最后一个可以通过调用Math.Round(number,1)来解决超过1000的值,然后使用相同的String.Format。
类似的东西:
String.Format("{0:#,##0.########}", number<1000 ? number : Math.Round(number,1));
答案 3 :(得分:2)
跟进OwenP(和“扩展”tvanfosson):
如果它很常见,并且你在C#3.0上,我会把它变成双重的扩展方法:
class MyExtensions
{
public static string ToFormmatedString(this double d)
{
// Take d and implement tvanfosson's code
}
}
现在你可以做任何一个双倍的事情:
double d = 1.005343;
string d_formatted = d.ToFormattedString();
答案 4 :(得分:1)
如果是我,我会编写一个自定义包装类并将tvanfosson的代码放入其ToString
方法中。这样你仍然可以使用double值,但几乎在所有情况下你都能获得正确的字符串表示。它看起来像这样:
class FormattedDouble
{
public double Value { get; set; }
protected overrides void ToString()
{
// tvanfosson's code to produce the right string
}
}
也许将它作为一个结构可能更好,但我怀疑它会产生很大的不同。你可以使用这样的类:
var myDouble = new FormattedDouble();
myDouble.Value = Math.Pi;
Console.WriteLine(myDouble);