使大小数字人类可读

我希望以人性化的方式在C#中打印我的小数字,例如:

3E-530µ0.000000456789456.789n

我知道C中BSD的Humanize_number ()函数,但只与bit int兼容,而不是浮点数和双精度数。 在C#中有相同的支持吗?

此外,在显示数字时应保持一定的精度,例如:

0.003596应显示为3.596µ ,而不是3.6µ (或更差, 3.6µ )。

这里可能的答案: 使用.NET格式化大数字但适用于负数log10会将数字截断为逗号后的1位数。 在我看来,这还远未完成。

我想如何呈现东西的例子:

 3000 3K 3300 3.3K 3333 3.333K 30000 30k 300000 300k 3000000 3M 3000003 3.000003M // or 3M if I specify "4 digits precision" 0.253 253m 0.0253 25.3m 0.00253 2.53m -0.253003 -253.003m 

我无法在SO中提出我的问题以找到相关的答案,所以如果问题已经得到解答,那就开火吧!

试试这个:

 static class Extensions { static string[] prefixes= { "f", "a", "p", "n", "μ", "m", string.Empty, "k", "M", "G", "T", "P", "E" }; public static string Nice(this double x, int significant_digits) { //Check for special numbers and non-numbers if(double.IsInfinity(x)||double.IsNaN(x)||x==0||significant_digits<=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= x==0? 0 : (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= x==0? 0 : (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)); } // find index for prefix. every 3 of sci is a new index int index=sci/3+6; if(index>=0&&index 

测试输出有四位有效数字:

  3.14159265358979E-19 = 314.2·10^-2 1.5707963267949E-18 = 1.571f 7.85398163397448E-18 = 7.854f 3.92699081698724E-17 = 39.27f 1.96349540849362E-16 = 196.3f 9.8174770424681E-16 = 981.7f 4.90873852123405E-15 = 4.909a 2.45436926061703E-14 = 24.54a 1.22718463030851E-13 = 122.7a 6.13592315154256E-13 = 613.6a 3.06796157577128E-12 = 3.068p 1.53398078788564E-11 = 15.34p 7.6699039394282E-11 = 76.70p 3.8349519697141E-10 = 383.5p 1.91747598485705E-09 = 1.917n 9.58737992428526E-09 = 9.587n 4.79368996214263E-08 = 47.94n 2.39684498107131E-07 = 239.7n 1.19842249053566E-06 = 1.198µ 5.99211245267829E-06 = 5.992µ 2.99605622633914E-05 = 29.96µ 0.000149802811316957 = 149.8µ 0.000749014056584786 = 749.0µ 0.00374507028292393 = 3.745m 0.0187253514146196 = 18.73m 0.0936267570730982 = 93.63m 0.468133785365491 = 468.1m 2.34066892682745 = 2.341 11.7033446341373 = 11.70 58.5167231706864 = 58.52 292.583615853432 = 292.6 1462.91807926716 = 1.463k 7314.5903963358 = 7.315k 36572.951981679 = 36.57k 182864.759908395 = 182.9k 914323.799541975 = 914.3k 4571618.99770987 = 4.572M 22858094.9885494 = 22.86M 114290474.942747 = 114.3M 571452374.713734 = 571.5M 2857261873.56867 = 2.857G 14286309367.8434 = 14.29G 71431546839.2168 = 71.43G 357157734196.084 = 357.2G 1785788670980.42 = 1.786T 8928943354902.1 = 8.929T 44644716774510.5 = 44.64T 223223583872552 = 223.2T 1.11611791936276E+15 = 1.116P 5.58058959681381E+15 = 5.581P 2.79029479840691E+16 = 27.90P 1.39514739920345E+17 = 139.5P 6.97573699601726E+17 = 697.6P 3.48786849800863E+18 = 3.488E 1.74393424900432E+19 = 17.44E 8.71967124502158E+19 = 87.20E 4.35983562251079E+20 = 436.0E 2.1799178112554E+21 = 2.180·10^21 

因为你希望小数显示为符号而不是很多0,你可以这样做:

 class Program { static void Main(string[] args) { //these are your "unit precedessors" char[] exponentsbig = new char[] {' ', 'k', 'M', 'G', 'T', 'P', 'E' }; char[] exponentssmall = new char[] { ' ', 'm', 'µ', 'n', 'p', 'a', 'f' }; //some example numbers long[] numbersBig = new long[] { 3000, 3003, 30000, 300000, 300003, 1594900000000000 }; double[] numbersSmall = new double[] { 0.0002, 0.245, 0.245003, 0.000004578 }; //some helper vars int counter = 0; bool edited = false; //let's have a look at what we produce;) string output = ""; //Big numbers incoming!! for (int i = 0; i < numbersBig.Length; i++) { counter=0; double myNumber = Convert.ToDouble(numbersBig[i]); do { edited = false; //something to prevent unnecessary unit-adding and making sure you still divide by 1000 if (myNumber/1000>1 ) { counter++; myNumber /= 1000; edited = true; } } while (edited); output += numbersBig[i] + " " + myNumber + exponentsbig[counter] + "\n"; } //small numbers incoming!! for (int i = 0; i < numbersSmall.Length; i++) { counter = 0; double myNumber = numbersSmall[i]; do { edited = false; //this will go to 3 digits after comma. you can make the compared smaller //to be more exact after the comma, but keep in mind you lose steps then if (myNumber < 1) { counter++; myNumber *= 1000; edited = true; } } while (edited); output += numbersSmall[i] + " " + myNumber + exponentssmall[counter] + "\n"; } //see what we did Console.Write(output); Console.ReadKey(); } } 

你能用DllImport来使用Humanize_Number函数吗? 详情请见此处:

在C#中动态加载dll

为什么不乘以10 ^(十进制后的计数)? 您可以在小数点后使用相同的数字计数来确定要显示的单位。 它比导入整个库要好得多。