2012-04-13 112 views
4

假设我有两个数字,0.0001和0.00001。如何将double值格式化为指定指数的E格式?

当我尝试使用在C#中的“e”符号进行格式化,我得到如下:

double val = 0.0001; 
Console.Out.WriteLine(val.ToString("e")) //prints 1e-4 

double val2 = 0.00001; 
Console.Out.WriteLine(val2.ToString("e")) //prints 1e-5 

但我想格式化既0.0001和0.00001,显示这样的同一指数:

0.0001〜> 100E-6 0.00001-> 10E-6

我怎样才能做到这一点?

+2

你将不得不写做到这一点的方法。科学记数法指定“e”之前的数字在1(含)和10(不含)之间,或者为零。换句话说,小数点左边必须有一位数,如果该位数为零,则小数点右边的所有数字也必须为零。 – phoog 2012-04-13 17:05:29

+0

另请参阅此问题:http://stackoverflow.com/questions/808104/engineering-notation-in-c – 2012-04-13 17:06:26

回答

6

如果你想这样的结果:

1.0  = 1.00 
    0.1  = 0.10 
    0.01  = 0.010 
    0.001 = 1.00e-3 
    0.0001 = 0.10e-3 
    0.00001 = 0.010e-3 
    0.000001 = 1.00e-6 

使用这种代码:

class Program 
{ 
    /// <summary> 
    /// Format a value using engineering notation. 
    /// </summary> 
    /// <example> 
    ///  Format("S4",-12345678.9) = "-12.34e-6" 
    ///  with 4 significant digits 
    /// </example> 
    /// <arg name="format">The format specifier</arg> 
    /// <arg name="value">The value</arg> 
    /// <returns>A string representing the value formatted according to the format specifier</returns> 
    public static string Format(string format, double value) 
    { 
     if(format.StartsWith("S")) 
     { 
      string dg=format.Substring(1); 
      int significant_digits; 
      int.TryParse(dg, out significant_digits); 
      if(significant_digits==0) significant_digits=4; 
      int sign; 
      double amt; 
      int exponent; 
      SplitEngineeringParts(value, out sign, out amt, out exponent); 
      return ComposeEngrFormat(significant_digits, sign, amt, exponent); 
     } 
     else 
     { 
      return value.ToString(format); 
     } 
    } 
    static void SplitEngineeringParts(double value, 
       out int sign, 
       out double new_value, 
       out int exponent) 
    { 
     sign=Math.Sign(value); 
     value=Math.Abs(value); 
     if(value>0.0) 
     { 
      if(value>1.0) 
      { 
       exponent=(int)(Math.Floor(Math.Log10(value)/3.0)*3.0); 
      } 
      else 
      { 
       exponent=(int)(Math.Ceiling(Math.Log10(value)/3.0)*3.0); 
      } 
     } 
     else 
     { 
      exponent=0; 
     } 
     new_value=value*Math.Pow(10.0, -exponent); 
     if(new_value>=1e3) 
     { 
      new_value/=1e3; 
      exponent+=3; 
     } 
     if(new_value<=1e-3&&new_value>0) 
     { 
      new_value*=1e3; 
      exponent-=3; 
     } 
    } 
    static string ComposeEngrFormat(int significant_digits, int sign, double v, int exponent) 
    { 
     int expsign=Math.Sign(exponent); 
     exponent=Math.Abs(exponent); 
     int digits=v>0?(int)Math.Log10(v)+1:0; 
     int decimals=Math.Max(significant_digits-digits, 0); 
     double round=Math.Pow(10, -decimals); 
     digits=v>0?(int)Math.Log10(v+0.5*round)+1:0; 
     decimals=Math.Max(significant_digits-digits, 0); 
     string t; 
     string f="0:F"; 
     if(exponent==0) 
     { 
      t=string.Format("{"+f+decimals+"}", sign*v); 
     } 
     else 
     { 
      t=string.Format("{"+f+decimals+"}e{1}", sign*v, expsign*exponent); 
     } 
     return t; 
    } 

    static void Main(string[] args) 
    { 
     Console.WriteLine("\t1.0  = {0}", Format("S3", 1.0)); 
     Console.WriteLine("\t0.1  = {0}", Format("S3", 0.1)); 
     Console.WriteLine("\t0.01  = {0}", Format("S3", 0.01)); 
     Console.WriteLine("\t0.001 = {0}", Format("S3", 0.001)); 
     Console.WriteLine("\t0.0001 = {0}", Format("S3", 0.0001)); 
     Console.WriteLine("\t0.00001 = {0}", Format("S3", 0.00001)); 
     Console.WriteLine("\t0.000001 = {0}", Format("S3", 0.000001)); 
    } 
} 
+0

谢谢,这正是我所需要的。 – sbenderli 2012-04-16 15:21:17

0

我想添加在做同样的事情,我的其他答案更简单的方法

/// <summary> 
/// Format a number with scientific exponents and specified sigificant digits. 
/// </summary> 
/// <param name="x">The value to format</param> 
/// <param name="significant_digits">The number of siginicant digits to show</param> 
/// <returns>The fomratted string</returns> 
public static string Sci(this double x, int significant_digits) 
{ 
    //Check for special numbers and non-numbers 
    if (double.IsInfinity(x)||double.IsNaN(x)||x==0) 
    { 
     return x.ToString(); 
    } 
    // extract sign so we deal with positive numbers only 
    int sign=Math.Sign(x); 
    x=Math.Abs(x); 
    // get scientific exponent, 10^3, 10^6, ... 
    int sci=(int)Math.Floor(Math.Log(x, 10)/3)*3; 
    // scale number to exponent found 
    x=x*Math.Pow(10, -sci); 
    // find number of digits to the left of the decimal 
    int dg=(int)Math.Floor(Math.Log(x, 10))+1; 
    // adjust decimals to display 
    int decimals=Math.Min(significant_digits-dg, 15); 
    // format for the decimals 
    string fmt=new string('0', decimals); 
    if (sci==0) 
    { 
     //no exponent 
     return string.Format("{0}{1:0."+fmt+"}", 
      sign<0?"-":string.Empty, 
      Math.Round(x, decimals)); 
    } 
    int index=sci/3+6; 
    // with 10^exp format 
    return string.Format("{0}{1:0."+fmt+"}e{2}", 
     sign<0?"-":string.Empty, 
     Math.Round(x, decimals), 
     sci); 
} 

所以测试代码

double x = 10000*Math.PI; 
for (int i = 0; i < 12; i++) 
{ 
    Debug.Print("{0,-25} {1,-12}", x, x.Sci(3)); 
    x/=10; 
} 

产生以下输出:

x       x.Sci(3) 
31415.9265358979   31.4e3  
3141.59265358979   3.14e3  
314.159265358979   314   
31.4159265358979   31.4   
3.14159265358979   3.14   
0.314159265358979   314e-3  
0.0314159265358979  31.4e-3  
0.00314159265358979  3.14e-3  
0.000314159265358979  314e-6  
3.14159265358979E-05  31.4e-6  
3.14159265358979E-06  3.14e-6  
3.14159265358979E-07  314e-9  
相关问题