【C#】Excel舍入函數Round、RoundUp、RoundDown的C#版

來源:互聯網
上載者:User

標籤:style   blog   http   color   ar   使用   strong   sp   div   

本人在C#中進行小數舍入的時候常常會懷念Excel中的Round、RoundUp、RoundDown這幾個函數,原因就是後者“接地氣”,比較符合俺小老百姓的舍入要求,啥“銀行家舍入法”就讓銀行家去用吧。先溫習一下這幾個Excel函數的功能:

Round(value, digits)

將value按四捨五入法進行舍入,保留digits位小數;當digits為負時,在小數點左側進行舍入;當value為負時,表現與正數完全相反。

舉例:Round(3.145, 2) = 3.15;Round(-3.145, 2) = -3.15;Round(3145, -2) = 3100

RoundUp(value, digits)

按遠離 0 的方向,將value向上舍入,保留digits位小數;當digits為負時,在小數點左側進行舍入

舉例:RoundUp(3.111, 2) = 3.12;RoundUp(-3.111, 2) = -3.12;RoundUp(3111, -2) = 3200

RoundDown(value, digits)

按靠近 0 的方向,將value向下舍入,保留digits位小數;當digits為負時,在小數點左側進行舍入

舉例:RoundDown(3.145, 2) = 3.14;RoundDown(-3.145, 2) = -3.14;RoundDown(3145, -2) = 3100

實現原理:

- 對於RoundUp和RoundDown,由於decimal或Math類的Ceiling和Floor方法(下稱C/F)只能取整,所以先根據要保留的位元,乘除得到可供C/F方法發揮的新值,然後就可以利用C/F得到舍入後的值,再乘/除回去,得到最終結果。此法市面常見。

舉例:1.114向上保留2位,首先1.114x100得到111.4,再用C(111.4)得到112,然後112 / 100,最終得到1.12

問題:由於要先對原值進行乘除,所以對於接近Max/Min、或精度過高的原值,這一步就會造成溢出,所以Up和Down不能應對特別大的值,但日常應用相信沒問題。

- 對於RoundEx方法,則直接封裝decimal.Round(decimal, MidpointRounding.AwayFromZero)得到結果。

實現說明:

- 以擴充方法提供,相容常規方法調用方式(廢話)。即可以3.145M.RoundEx(2),也可以MathEx.RoundEx(3.145M, 2)

- 每個方法以decimal和double兩種類型提供重載,共6個方法

- 以decimal類型為基礎進行實現,double版只是重用+類型轉換。之所以不對double進行實現,不是因為偷懶,而是因為浮點運算容易扯蛋,如555.55x100=55554.999999999993。關於浮點運算的不可靠性,可參看:http://www.cnblogs.com/ethancai/articles/1237012.html

- 四捨五入函數命名為RoundEx是因為decimal類已經存在一個叫Round的靜態方法,如果不錯開,將不能以擴充方式3M.Round()進行調用。而且雖然.net在命名上具有極大的包容度,但我認為還是盡量避開FCL命名的好,無謂去“享受”這種自由度

- 幾個方法之所以都要先判斷一下保留位元,而沒有直接使用10的digits次方進行運算,是想盡量沿用decimal類型的原生方法,減少沒有必要的數學運算。咱追求的不是極簡的代碼,而是效能。當然,沒測試過~雞蛋砸來中...

廢話了一堆,上代碼:

/// <summary>/// 數學類擴充方法/// </summary>public static class MathEx{    /// <summary>    /// 遠離 0 向上舍入    /// </summary>    public static decimal RoundUp(this decimal value, sbyte digits)    {        if (digits == 0)        {            return (value >= 0 ? decimal.Ceiling(value) : decimal.Floor(value));        }        decimal multiple = Convert.ToDecimal(Math.Pow(10, digits));        return (value >= 0 ? decimal.Ceiling(value * multiple) : decimal.Floor(value * multiple)) / multiple;    }    /// <summary>    /// 靠近 0 向下舍入    /// </summary>    public static decimal RoundDown(this decimal value, sbyte digits)    {        if (digits == 0)        {            return (value >= 0 ? decimal.Floor(value) : decimal.Ceiling(value));        }        decimal multiple = Convert.ToDecimal(Math.Pow(10, digits));        return (value >= 0 ? decimal.Floor(value * multiple) : decimal.Ceiling(value * multiple)) / multiple;    }    /// <summary>    /// 四捨五入    /// </summary>    public static decimal RoundEx(this decimal value, sbyte digits)    {        if (digits >= 0)        {            return decimal.Round(value, digits, MidpointRounding.AwayFromZero);        }        decimal multiple = Convert.ToDecimal(Math.Pow(10, -digits));        return decimal.Round(value / multiple, MidpointRounding.AwayFromZero) * multiple;    }    /// <summary>    /// 遠離 0 向上舍入    /// </summary>    public static double RoundUp(this double value, sbyte digits)    {        return decimal.ToDouble(Convert.ToDecimal(value).RoundUp(digits));    }    /// <summary>    /// 靠近 0 向下舍入    /// </summary>    public static double RoundDown(this double value, sbyte digits)    {        return decimal.ToDouble(Convert.ToDecimal(value).RoundDown(digits));    }    /// <summary>    /// 四捨五入    /// </summary>    public static double RoundEx(this double value, sbyte digits)    {        return decimal.ToDouble(Convert.ToDecimal(value).RoundEx(digits));    }}

- 文畢 -

【C#】Excel舍入函數Round、RoundUp、RoundDown的C#版

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.