C# Round源码

来源:互联网 发布:淘宝退款怎么退一部分 编辑:程序博客网 时间:2024/06/03 06:26

在日常开发中经常遇到四舍五入的情况比如 Math.Round(1.25, 1),首先我们要知道这里的Round 其实是银行家算法,具体可以参考Round() 四舍五入 js银行家算法 那么C#是如何实现的了,我们来看看decimal的round实现如下:

       [System.Security.SecuritySafeCritical]  // auto-generated        public static Decimal Round(Decimal d, int decimals)        {            FCallRound (ref d, decimals);            return d;        }        public static Decimal Round(Decimal d, MidpointRounding mode) {            return Round(d, 0, mode);        }            [System.Security.SecuritySafeCritical]  // auto-generated        public static Decimal Round(Decimal d, int decimals, MidpointRounding mode) {            if ((decimals < 0) || (decimals > 28))                throw new ArgumentOutOfRangeException("decimals", Environment.GetResourceString("ArgumentOutOfRange_DecimalRound"));            if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) {                            throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumValue", mode, "MidpointRounding"), "mode");            }            Contract.EndContractBlock();            if (mode == MidpointRounding.ToEven) {                FCallRound (ref d, decimals);            }            else {                InternalRoundFromZero(ref d, decimals);            }            return d;        }        [System.Security.SecurityCritical]  // auto-generated        [ResourceExposure(ResourceScope.None)]        [MethodImplAttribute(MethodImplOptions.InternalCall)]        private static extern void FCallRound(ref Decimal d, int decimals);          // Does an in-place round the specified number of digits, rounding mid-point values        // away from zero        private static void InternalRoundFromZero(ref Decimal d, int decimalCount) {            Int32 scale = (d.flags & ScaleMask) >> ScaleShift;            Int32 scaleDifference = scale - decimalCount;            if (scaleDifference <= 0) {                return;            }            // Divide the value by 10^scaleDifference            UInt32 lastRemainder;            UInt32 lastDivisor;            do {                Int32 diffChunk = (scaleDifference > MaxInt32Scale) ? MaxInt32Scale : scaleDifference;                lastDivisor = Powers10[diffChunk];                lastRemainder = InternalDivRemUInt32(ref d, lastDivisor);                scaleDifference -= diffChunk;            } while (scaleDifference > 0);                        // Round away from zero at the mid point            if (lastRemainder >= (lastDivisor >> 1)) {                InternalAddUInt32RawUnchecked(ref d, 1);            }                        // the scale becomes the desired decimal count            d.flags = ((decimalCount << ScaleShift) & ScaleMask) | (d.flags & SignMask);        }

所以我们如果想要四舍五入 那么方法必须穿入MidpointRounding 参数,调用托管代码;不传这是银行家算法调用非托管代码,从性能的角度讲应该竟可能调用托管代码。所以除非有要求,尽力调用托管代码吧。

原创粉丝点击