在C#中若是float、double、decimal類型的值,小數點後的0太多時,C#會用科學記數法來表示小數的值。spa
例以下面的double類型0.00009,若是咱們直接將其用ToString()方法轉換爲字符串,就會變爲科學記數法9E-05code
double number = 0.00009; string defaultNumber = number.ToString(); //9E-05
此外若是float、double、decimal類型的值只有整數位,且整數後面有不少0,C#也會用科學記數法來表示整數的值,例以下面的double類型210000000000000000,若是咱們直接將其用ToString()方法轉換爲字符串,就會變爲科學記數法2.1E+17orm
double number = 210000000000000000; string defaultNumber = number.ToString(); //2.1E+17
因此咱們能夠經過顯式聲明轉換後字符串的格式,避免在C#中出現科學記數法:blog
using System; namespace NetCoreFloat { class Program { static void Main(string[] args) { double number = 0.00009; string defaultNumber = number.ToString(); //9E-05 string numberFromToString = number.ToString("N5"); //0.00009 string numberFromStringFormat = string.Format("{0:F5}", number); //0.00009 Console.WriteLine("Press any key to end..."); Console.ReadKey(); } } }
雖然上面的代碼可讓小數轉換爲字符串後不是科學記數法,可是很明顯咱們須要準確地知道小數點後會有多少位小數,才能保證轉換後的精度不會丟失。ci
若是咱們將轉換格式的精度設置得太小,就會形成精度損失,以下所示:字符串
using System; namespace NetCoreFloat { class Program { static void Main(string[] args) { double number = 0.00009; string defaultNumber = number.ToString(); //9E-05 string numberFromToString = number.ToString("N3"); //0.000 string numberFromStringFormat = string.Format("{0:F3}", number); //0.000 Console.WriteLine("Press any key to end..."); Console.ReadKey(); } } }
而若是咱們將轉換格式的精度設置得過大,又會在小數最後產生多餘的0,以下所示:get
using System; namespace NetCoreFloat { class Program { static void Main(string[] args) { double number = 0.00009; string defaultNumber = number.ToString(); //9E-05 string numberFromToString = number.ToString("N10"); //0.0000900000 string numberFromStringFormat = string.Format("{0:F10}", number); //0.0000900000 Console.WriteLine("Press any key to end..."); Console.ReadKey(); } } }
對此咱們須要在轉換格式中使用#字符,#字符不會在小數最後產生多餘的0,以下所示:string
using System; namespace NetCoreFloat { class Program { static void Main(string[] args) { double number = 0.00009; string numberFromToString = number.ToString("0.#####"); //0.00009 numberFromToString = number.ToString("0.##########"); //0.00009 number = 100.00009; numberFromToString = number.ToString("0.#####"); //100.00009 numberFromToString = number.ToString("0.##########"); //100.00009 number = 210000000000000000; numberFromToString = number.ToString("0.#####"); //210000000000000000 numberFromToString = number.ToString("0.##########"); //210000000000000000 Console.WriteLine("Press any key to end..."); Console.ReadKey(); } } }
實際上咱們能夠最大聲明339個#字符,這樣能夠保證全部小數都能被正確地轉換爲字符串:it
using System; namespace NetCoreFloat { class Program { static void Main(string[] args) { double number = 0.00009; string numberFromToString = number.ToString("0." + new string('#', 339));//0.00009 Console.WriteLine("Press any key to end..."); Console.ReadKey(); } } }
咱們也能夠聲明一個類FormatStrings,將339個#字符聲明爲一個字符串常量DoubleFixedPoint,這樣用起來也會更方便:io
using System; namespace NetCoreFloat { public static class FormatStrings { public const string DoubleFixedPoint = "0.###################################################################################################################################################################################################################################################################################################################################################"; } class Program { static void Main(string[] args) { double number = 0.00009; string numberFromToString = number.ToString(FormatStrings.DoubleFixedPoint);//0.00009 Console.WriteLine("Press any key to end..."); Console.ReadKey(); } } }
C#浮點數的精度問題
咱們這裏就拿double類型來舉例,float和decimal類型以此類推, double的最大值是(double.MaxValue):
179769313486232000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
其中有15位非0數字,也就是前面的179769313486232,那麼它表示double類型能夠存儲整數位加小數位一共15位的有效數字(也就是說double類型中,第1位和最後1位非0的數字,一共能有15位)。
例如若是咱們聲明一個18位的小數number,而後經過ToString方法將其輸出爲字符串:
double number = 1234567890.12345678;//整數10位,小數8位 string numberFromToString = number.ToString("0." + new string('#', 339));//1234567890.12346
能夠看到ToString方法輸出的是1234567890.12346,整數位加小數位一共只有15位,其中最後一位小數數字是6,是由於被#字符四捨五入了。
如今咱們提升整數位的位數到13位,聲明一個一共21位的小數,咱們看看結果如何:
double number = 1234567890123.12345678;//整數13位,小數8位 string numberFromToString = number.ToString("0." + new string('#', 339));//1234567890123.12
能夠看到此次最後ToString方法輸出的是1234567890123.12,整數位加小數位仍是一共只有15位,而此次因爲整數位佔用了15位中的13位數字,因此小數位只剩下2位數字。
接下來咱們聲明一個一共20位的整數給double類型,看看結果如何:
double number = 12345678901231211111;//整數20位 string numberFromToString = number.ToString("0." + new string('#', 339));//12345678901231200000
能夠看到此次最後ToString方法輸出的是12345678901231200000,緣由就是由於double類型最大隻能存儲15位有效數字,因此最後5位1被截斷了變爲了0,只剩下了前面15位有效數字。
參考文獻:
Converting numbers to strings without scientific notation in C#