Design

Design
asp.net mvc

2019年1月30日 星期三

C#基礎 關於float、double、decimal 浮點計算精度問題

C#中關於浮點計算 float、double、decimal  有這三中 實數型可以使用
但是我們都知道使用float、double會有小數點計算不準確的情況
特別是跟錢有關係的最好都使用高精準度decimal,知所以會叫高精準度就代表也有精度損失的時候,不過跟比float、double算是商業上夠用了等等下面會舉個例子

我們先來看小數點計算精度損失的例子
可以發現我們float、double計算都出現精度損失的問題這種問題如果不理會
後續會造成很大的嚴重後果 所以最好都使用decimal



當然我剛有提到decimal雖然擁有高精度但是就代表也會有精度損失的問題下面就舉個例子
可以看到我們的結果不是我們要的10000000000000000000000000000.1
不過這是比較極端的例子 正常也不會到這麼大的位數



再來我們再進行比對時資料結構一些問題 往往會需要先toString()在進行比對
可以發現我們float、double都是 true 原因是轉為字串float、double會自動把小數點後的零去除
但是卻發現decimal是false  原因是轉為字串 小數點後的零被保存下來
這時我們需要去除小數點後的零  stackoverflow 上的大神 有一招很酷的方法
就是我們的decimal 除掉 1.000000000000000000000000000000000
就會神奇發現我們小數點後的零都不見了 這時我們就可以擴充成方法作為使用  在進行比對我們就可以解決上述的問題



以上是C# 浮點精度 需要注意的事項  還是乖乖用decimal吧  雖然這是small tips不過還是開發時不可不注意的東西,以下是程式碼



namespace 練習
{
    class Program
    {
        static void Main(string[] args)
        {

            //float
            float f = 1.1f;
            f += 1.1f;

            //double
            double d = 1.1d;
            d += 1.1d;

            //decimal
            decimal de = 1.1m;
            de += 1.1m;

            Console.WriteLine("{0:G50}", f);
            Console.WriteLine("{0:G50}", d);
            Console.WriteLine("{0:G50}", de);


            //decimal 精度損失的例子
            decimal dd = 10000000000000000000000000000m;
            dd += 0.1m;
            Console.WriteLine("{0:G50}", dd);

            //float 比對
            float f1 = 1.1f;
            float f2 = 1.100f;
            Console.WriteLine(f1.ToString() == f2.ToString());

            //decimal 比對
            double d1 = 1.1d;
            double d2 = 1.100d;
            Console.WriteLine(d1.ToString() == d2.ToString());

            //decimal 比對
            decimal de1 = 1.1m;
            decimal de2 = 1.100m;
            Console.WriteLine(de1.ToString() == de2.ToString());

            decimal Money1 = 1.1m;
            decimal Money2 = 1.100m;

            //去除小數點後的零 方便作比對用
            Console.WriteLine(Money1.Streamline().ToString() == Money2.Streamline().ToString());


            Console.Read();
        }

    }


    
}

namespace CustomExtensions
{
    public static class Extension
    {
        public static decimal Streamline(this decimal d)
        {
            return d / 1.000000000000000000000000000000000m;
        }
    }
}

沒有留言:

張貼留言