怎樣避免C#中將小數轉換爲字符串時出現科學記數法

在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#

Double to string conversion without scientific notation

相關文章
相關標籤/搜索