{"id":213,"date":"2020-09-08T06:33:04","date_gmt":"2020-09-08T06:33:04","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=213"},"modified":"2021-06-20T12:15:50","modified_gmt":"2021-06-20T12:15:50","slug":"bigdecimal-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2020\/09\/08\/bigdecimal-cs\/","title":{"rendered":"BigDecimal.cs"},"content":{"rendered":"\n<p>Arbitrary Precision Signed BigDecimal<\/p>\n\n\n\n<p>Updated: Jun-15,2021<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System;\nusing System.Diagnostics;\nusing System.Numerics;\nusing System.Runtime.InteropServices;\nusing System.Text;\n[Serializable]\n[DebuggerDisplay(\"{DDisplay}\")]\npublic struct BigDecimal : IComparable, IComparable&lt;BigDecimal>, IEquatable&lt;BigDecimal>\n{\n    private const           int          MaxFactorials    = 200;\n    private static          int          _bitWidth        = 2048;\n    public static           float        MaxPrecision     = _bitWidth \/ 64f * 20f;\n    private static readonly BigInteger   DoublePrecision  = BigInteger.Pow(10, 308);\n    private static readonly BigInteger   DoubleMaxValue   = (BigInteger)double.MaxValue;\n    private static readonly BigInteger   DoubleMinValue   = (BigInteger)double.MinValue;\n    private static readonly BigInteger   DecimalPrecision = BigInteger.Pow(10, 28);\n    private static readonly BigInteger   DecimalMaxValue  = (BigInteger)decimal.MaxValue;\n    private static readonly BigInteger   DecimalMinValue  = (BigInteger)decimal.MinValue;\n    private static          BigDecimal[] Factorials;\n    private                 int          _scale;\n    private                 BigInteger   _unscaledValue;\n    public BigDecimal(BigInteger value) : this(value, 0)\n    {\n    }\n    public BigDecimal(xIntX value) : this((BigInteger)value, 0)\n    {\n    }\n    public BigDecimal(BigIntX value) : this((BigInteger)value, 0)\n    {\n    }\n    public BigDecimal(BigInteger value, int scale)\n    {\n        _unscaledValue = value;\n        _scale         = scale;\n    }\n    public BigDecimal(long value) : this(value, 0)\n    {\n    }\n    public BigDecimal(double value) : this((decimal)value)\n    {\n    }\n    public BigDecimal(float value) : this((decimal)value)\n    {\n    }\n    public BigDecimal(byte[] value)\n    {\n        var number = new byte[value.Length - 4];\n        var flags  = new byte[4];\n        Array.Copy(value, 0,                number, 0, number.Length);\n        Array.Copy(value, value.Length - 4, flags,  0, 4);\n        _unscaledValue = new BigInteger(number);\n        _scale         = BitConverter.ToInt32(flags, 0);\n    }\n    public BigDecimal(BigRational value)\n    {\n        var num       = (BigDecimal)value.Numerator;\n        var den       = (BigDecimal)value.Denominator;\n        var bigDecRes = num \/ den;\n        _unscaledValue = bigDecRes._unscaledValue;\n        _scale         = bigDecRes.Scale;\n    }\n    public BigDecimal(BigDecimal value)\n    {\n        _unscaledValue = value._unscaledValue;\n        _scale         = value.Scale;\n    }\n    public BigDecimal(decimal value)\n    {\n        var bytes = new byte[16];\n        var bits  = decimal.GetBits(value);\n        var lo    = bits[0];\n        var mid   = bits[1];\n        var hi    = bits[2];\n        var flags = bits[3];\n        bytes[0]  = (byte)lo;\n        bytes[1]  = (byte)(lo >> 8);\n        bytes[2]  = (byte)(lo >> 0x10);\n        bytes[3]  = (byte)(lo >> 0x18);\n        bytes[4]  = (byte)mid;\n        bytes[5]  = (byte)(mid >> 8);\n        bytes[6]  = (byte)(mid >> 0x10);\n        bytes[7]  = (byte)(mid >> 0x18);\n        bytes[8]  = (byte)hi;\n        bytes[9]  = (byte)(hi >> 8);\n        bytes[10] = (byte)(hi >> 0x10);\n        bytes[11] = (byte)(hi >> 0x18);\n        bytes[12] = (byte)flags;\n        bytes[13] = (byte)(flags >> 8);\n        bytes[14] = (byte)(flags >> 0x10);\n        bytes[15] = (byte)(flags >> 0x18);\n        var unscaledValueBytes = new byte[12];\n        Array.Copy(bytes, unscaledValueBytes, unscaledValueBytes.Length);\n        var unscaledValue = new BigInteger(unscaledValueBytes);\n        var scale         = bytes[14];\n        if (bytes[15] == 128)\n            unscaledValue *= BigInteger.MinusOne;\n        _unscaledValue = unscaledValue;\n        _scale         = scale;\n    }\n    public BigDecimal(string value)\n    {\n        if (!value.ContainsOnly(\"0123456789+-.eE\"))\n            throw new Exception($\"Input value must only contain these '0123456789+-.eE', value'{value}\");\n        var len      = value.Length;\n        var start    = 0;\n        var point    = 0;\n        var dot      = -1;\n        var negative = false;\n        if (value[0] == '+')\n        {\n            ++start;\n            ++point;\n        }\n        else if (value[0] == '-')\n        {\n            ++start;\n            ++point;\n            negative = true;\n        }\n        while (point &lt; len)\n        {\n            var c = value[point];\n            if (c == '.')\n            {\n                if (dot >= 0)\n                    throw new Exception($\"There are multiple '.'s in the value {value}\");\n                dot = point;\n            }\n            else if (c == 'e' || c == 'E')\n            {\n                break;\n            }\n            ++point;\n        }\n        string val;\n        if (dot >= 0)\n        {\n            val    = value.Substring(start, dot) + value.Substring(dot + 1, point - (dot + 1));\n            _scale = point                       - 1 - dot;\n        }\n        else\n        {\n            val    = value.Substring(start, point);\n            _scale = 0;\n        }\n        if (val.Length == 0)\n            throw new Exception($\"There are no digits in the value {value}\");\n        if (negative)\n            val = \"-\" + val;\n        _unscaledValue = val.BigIntegerBase10();\n        if (point &lt; len)\n            try\n            {\n                point++;\n                switch (value[point])\n                {\n                    case '+':\n                    {\n                        point++;\n                        if (point >= len)\n                            throw new Exception($\"No exponent following e or E. Value {value}\");\n                        var scale = value.Substring(point);\n                        _scale -= int.Parse(scale);\n                        return;\n                    }\n                    case '-':\n                    {\n                        point++;\n                        if (point >= len)\n                            throw new Exception($\"No exponent following e or E. Value {value}\");\n                        var scale = value.Substring(point);\n                        _scale += int.Parse(scale);\n                        return;\n                    }\n                    default:\n                        throw new Exception($\"Malformed exponent in value {value}\");\n                }\n            }\n            catch (Exception ex)\n            {\n                throw new Exception($\"Malformed exponent in value {value}\");\n            }\n    }\n    public int BitWidth\n    {\n        get => _bitWidth;\n        set\n        {\n            _bitWidth    = value;\n            MaxPrecision = _bitWidth \/ 64f * 20f;\n        }\n    }\n    private string DDisplay => ToString();\n    public static BigDecimal Zero\n    {\n        get;\n    } = new(BigInteger.Zero);\n    public static BigDecimal One\n    {\n        get;\n    } = new(BigInteger.One);\n    public static BigDecimal MinusOne\n    {\n        get;\n    } = new(BigInteger.MinusOne);\n    public bool IsEven       => _unscaledValue.IsEven;\n    public bool IsOne        => _unscaledValue.IsOne;\n    public bool IsPowerOfTwo => _unscaledValue.IsPowerOfTwo;\n    public bool IsZero       => _unscaledValue.IsZero;\n    public int  Sign         => _unscaledValue.Sign;\n    public int Scale\n    {\n        get => _scale;\n        private set => _scale = value;\n    }\n    public BigInteger UnscaledValue  => _unscaledValue;\n    public BigDecimal WholePart      => BigInteger.Divide(_unscaledValue, BigInteger.Pow(10, Scale));\n    public BigDecimal FractionalPart => this - WholePart;\n    public int DecimalPlaces\n    {\n        get\n        {\n            var a       = new BigDecimal(_unscaledValue);\n            var dPlaces = 0;\n            if (a.Sign == 0)\n                return 1;\n            if (a.Sign &lt; 0)\n                try\n                {\n                    a = -a;\n                }\n                catch (Exception ex)\n                {\n                    return 0;\n                }\n            var biRadix = new BigDecimal(10);\n            while (a > 0)\n                try\n                {\n                    a \/= biRadix;\n                    dPlaces++;\n                }\n                catch (Exception ex)\n                {\n                    break;\n                }\n            return dPlaces;\n        }\n    }\n    int IComparable.CompareTo(object obj)\n    {\n        if (obj == null)\n            return 1;\n        if (!(obj is BigDecimal))\n            throw new Exception(\"Argument must be of type BigDecimal.\");\n        return Compare(this, (BigDecimal)obj);\n    }\n    public int CompareTo(BigDecimal other)\n    {\n        return Compare(this, other);\n    }\n    public bool Equals(BigDecimal other)\n    {\n        return _unscaledValue == other._unscaledValue &amp;&amp; _scale == other.Scale;\n    }\n    public override bool Equals(object obj)\n    {\n        if (obj == null)\n            return false;\n        if (!(obj is BigDecimal))\n            return false;\n        return Equals((BigDecimal)obj);\n    }\n    public static BigDecimal Round(BigDecimal number, int decimalPlaces)\n    {\n        BigDecimal power = BigInteger.Pow(10, decimalPlaces);\n        number *= power;\n        return number >= 0 ? (BigInteger)(number + 0.5) \/ power : (BigInteger)(number - 0.5) \/ power;\n    }\n    public void Round(int decimalPlaces)\n    {\n        var        number = this;\n        BigDecimal power  = BigInteger.Pow(10, decimalPlaces);\n        number *= power;\n        var n = number >= 0 ? (BigInteger)(number + 0.5) \/ power : (BigInteger)(number - 0.5) \/ power;\n        _unscaledValue = n._unscaledValue;\n        _scale         = n.Scale;\n    }\n    public override int GetHashCode()\n    {\n        return UnscaledValue.GetHashCode() ^ _scale.GetHashCode();\n    }\n    public override string ToString()\n    {\n        return ToStringInt();\n    }\n    public string ToString(IFormatProvider provider)\n    {\n        var number = _unscaledValue.ToString(\"G\");\n        if (_scale > 0 &amp;&amp; WholePart != 0 &amp;&amp; number.Length - _scale >= 0)\n            return number.Insert(number.Length - _scale, \".\");\n        return _unscaledValue.ToString(provider);\n    }\n    private string ToStringInt()\n    {\n        var number = _unscaledValue.ToString(\"G\");\n        if (_scale > 0 &amp;&amp; WholePart != 0 &amp;&amp; number.Length - _scale >= 0)\n            return number.Insert(number.Length - _scale, \".\");\n        StringBuilder buf;\n        var           intString      = _unscaledValue.ToString();\n        var           insertionPoint = intString.Length - _scale;\n        if (insertionPoint == 0)\n            return (Sign &lt; 0 ? \"-0.\" : \"0.\") + intString;\n        if (insertionPoint > 0)\n        {\n            buf = new StringBuilder(intString);\n            buf.Insert(insertionPoint, '.');\n            if (Sign &lt; 0)\n                buf.Insert(0, '-');\n        }\n        else\n        {\n            buf = new StringBuilder(3 - insertionPoint + intString.Length);\n            buf.Append(Sign &lt; 0 ? \"-0.\" : \"0.\");\n            for (var i = 0; i &lt; -insertionPoint; i++)\n                buf.Append('0');\n            buf.Append(intString);\n        }\n        if (_scale == 0)\n            buf.Append(\"0\");\n        return buf.ToString();\n    }\n    public static BigDecimal Parse(string value)\n    {\n        return new BigDecimal(value);\n    }\n    public byte[] ToByteArray()\n    {\n        var unscaledValue = _unscaledValue.ToByteArray();\n        var scale         = BitConverter.GetBytes(_scale);\n        var bytes         = new byte[unscaledValue.Length + scale.Length];\n        Array.Copy(unscaledValue, 0, bytes, 0,                    unscaledValue.Length);\n        Array.Copy(scale,         0, bytes, unscaledValue.Length, scale.Length);\n        return bytes;\n    }\n    public (byte[] unscaledValue, byte[] scale) ToByteArrays()\n    {\n        return (_unscaledValue.ToByteArray(), BitConverter.GetBytes(_scale));\n    }\n    public static BigDecimal Abs(BigDecimal value)\n    {\n        return value._unscaledValue.Sign &lt; 0 ? -value : value;\n    }\n    public static BigDecimal Negate(BigDecimal value)\n    {\n        return new BigDecimal(BigInteger.Negate(value._unscaledValue), value.Scale);\n    }\n    public static BigDecimal Add(BigDecimal x, BigDecimal y)\n    {\n        return x + y;\n    }\n    public static BigDecimal Subtract(BigDecimal x, BigDecimal y)\n    {\n        return x - y;\n    }\n    public static BigDecimal Multiply(BigDecimal x, BigDecimal y)\n    {\n        return x * y;\n    }\n    public static BigDecimal Divide(BigDecimal dividend, BigDecimal divisor)\n    {\n        return dividend \/ divisor;\n    }\n    public static BigDecimal Pow(BigDecimal baseValue, BigInteger exponent)\n    {\n        if (exponent.Sign == 0)\n            return One;\n        if (exponent.Sign &lt; 0)\n        {\n            if (baseValue == Zero)\n                throw new Exception(\"Cannot raise zero to a negative power.\");\n            baseValue = One \/ baseValue;\n            exponent  = BigInteger.Negate(exponent);\n        }\n        var result = baseValue;\n        while (exponent > BigInteger.One)\n        {\n            result *= baseValue;\n            exponent--;\n        }\n        return result;\n    }\n    public static int Compare(BigDecimal r1, BigDecimal r2)\n    {\n        return (r1 - r2)._unscaledValue.Sign;\n    }\n    public static bool operator ==(BigDecimal x, BigDecimal y)\n    {\n        return x.Equals(y);\n    }\n    public static bool operator !=(BigDecimal x, BigDecimal y)\n    {\n        return !x.Equals(y);\n    }\n    public static bool operator &lt;(BigDecimal x, BigDecimal y)\n    {\n        return Compare(x, y) &lt; 0;\n    }\n    public static bool operator &lt;=(BigDecimal x, BigDecimal y)\n    {\n        return Compare(x, y) &lt;= 0;\n    }\n    public static bool operator >(BigDecimal x, BigDecimal y)\n    {\n        return Compare(x, y) > 0;\n    }\n    public static bool operator >=(BigDecimal x, BigDecimal y)\n    {\n        return Compare(x, y) >= 0;\n    }\n    public static BigDecimal operator +(BigDecimal value)\n    {\n        return value;\n    }\n    public static BigDecimal operator -(BigDecimal value)\n    {\n        return new BigDecimal(-value._unscaledValue, value.Scale);\n    }\n    public static BigDecimal operator ++(BigDecimal value)\n    {\n        return value + One;\n    }\n    public static BigDecimal operator --(BigDecimal value)\n    {\n        return value - One;\n    }\n    public static BigDecimal operator +(BigDecimal left, BigDecimal right)\n    {\n        BigDecimal ret;\n        if (left.Scale >= right.Scale)\n        {\n            ret = left;\n        }\n        else\n        {\n            var value = left._unscaledValue * BigInteger.Pow(10, right.Scale - left.Scale);\n            ret = new BigDecimal(value, right.Scale);\n        }\n        BigDecimal ret1;\n        if (right.Scale >= left.Scale)\n        {\n            ret1 = right;\n        }\n        else\n        {\n            var value1 = right._unscaledValue * BigInteger.Pow(10, left.Scale - right.Scale);\n            ret1 = new BigDecimal(value1, left.Scale);\n        }\n        return new BigDecimal(ret._unscaledValue + ret1._unscaledValue, ret.Scale);\n    }\n    public static BigDecimal operator -(BigDecimal left, BigDecimal right)\n    {\n        BigDecimal ret;\n        if (left.Scale >= right.Scale)\n        {\n            ret = left;\n        }\n        else\n        {\n            var value = left._unscaledValue * BigInteger.Pow(10, right.Scale - left.Scale);\n            ret = new BigDecimal(value, right.Scale);\n        }\n        BigDecimal ret1;\n        if (right.Scale >= left.Scale)\n        {\n            ret1 = right;\n        }\n        else\n        {\n            var value1 = right._unscaledValue * BigInteger.Pow(10, left.Scale - right.Scale);\n            ret1 = new BigDecimal(value1, left.Scale);\n        }\n        return new BigDecimal(ret._unscaledValue - ret1._unscaledValue, ret.Scale);\n    }\n    public static BigDecimal operator *(BigDecimal left, BigDecimal right)\n    {\n        return new BigDecimal(left._unscaledValue * right._unscaledValue, left.Scale + right.Scale);\n    }\n    public static BigDecimal operator \/(BigDecimal left, BigDecimal right)\n    {\n        var value = left._unscaledValue;\n        var scale = left.Scale;\n        while (scale > 0 &amp;&amp; value % 10 == 0)\n        {\n            value \/= 10;\n            scale--;\n        }\n        var v1     = new BigDecimal(value, scale);\n        var value1 = right._unscaledValue;\n        var scale1 = right.Scale;\n        while (scale1 > 0 &amp;&amp; value1 % 10 == 0)\n        {\n            value1 \/= 10;\n            scale1--;\n        }\n        var v2 = new BigDecimal(value1, scale1);\n        while (v1.Scale > 0 || v2.Scale > 0)\n        {\n            if (v1.Scale > 0)\n                v1 = new BigDecimal(v1._unscaledValue, v1.Scale - 1);\n            else\n                v1 = new BigDecimal(v1._unscaledValue * 10, 0);\n            if (v2.Scale > 0)\n                v2 = new BigDecimal(v2._unscaledValue, v2.Scale - 1);\n            else\n                v2 = new BigDecimal(v2._unscaledValue * 10, 0);\n        }\n        var factor  = 0;\n        var v1Value = v1._unscaledValue;\n        while (factor &lt; (int)MaxPrecision &amp;&amp; v1Value % v2._unscaledValue != 0)\n        {\n            v1Value *= 10;\n            factor++;\n        }\n        return new BigDecimal(v1Value \/ v2._unscaledValue, factor);\n    }\n    public static BigDecimal operator %(BigDecimal left, BigDecimal right)\n    {\n        var value = left._unscaledValue;\n        var scale = left.Scale;\n        while (scale > 0 &amp;&amp; value % 10 == 0)\n        {\n            value \/= 10;\n            scale--;\n        }\n        var v1     = new BigDecimal(value, scale);\n        var value1 = right._unscaledValue;\n        var scale1 = right.Scale;\n        while (scale1 > 0 &amp;&amp; value1 % 10 == 0)\n        {\n            value1 \/= 10;\n            scale1--;\n        }\n        var v2 = new BigDecimal(value1, scale1);\n        while (v1.Scale > 0 || v2.Scale > 0)\n        {\n            if (v1.Scale > 0)\n                v1 = new BigDecimal(v1._unscaledValue, v1.Scale - 1);\n            else\n                v1 = new BigDecimal(v1._unscaledValue * 10, 0);\n            if (v2.Scale > 0)\n                v2 = new BigDecimal(v2._unscaledValue, v2.Scale - 1);\n            else\n                v2 = new BigDecimal(v2._unscaledValue * 10, 0);\n        }\n        return new BigDecimal(v1._unscaledValue % v2._unscaledValue);\n    }\n    public static explicit operator sbyte(BigDecimal value)\n    {\n        return (sbyte)BigInteger.Divide(value._unscaledValue, BigInteger.Pow(10, value.Scale));\n    }\n    public static explicit operator ushort(BigDecimal value)\n    {\n        return (ushort)BigInteger.Divide(value._unscaledValue, BigInteger.Pow(10, value.Scale));\n    }\n    public static explicit operator uint(BigDecimal value)\n    {\n        return (uint)BigInteger.Divide(value._unscaledValue, BigInteger.Pow(10, value.Scale));\n    }\n    public static explicit operator ulong(BigDecimal value)\n    {\n        return (ulong)BigInteger.Divide(value._unscaledValue, BigInteger.Pow(10, value.Scale));\n    }\n    public static explicit operator byte(BigDecimal value)\n    {\n        return (byte)BigInteger.Divide(value._unscaledValue, BigInteger.Pow(10, value.Scale));\n    }\n    public static explicit operator short(BigDecimal value)\n    {\n        return (short)BigInteger.Divide(value._unscaledValue, BigInteger.Pow(10, value.Scale));\n    }\n    public static explicit operator int(BigDecimal value)\n    {\n        return (int)BigInteger.Divide(value._unscaledValue, BigInteger.Pow(10, value.Scale));\n    }\n    public static explicit operator long(BigDecimal value)\n    {\n        return (long)BigInteger.Divide(value._unscaledValue, BigInteger.Pow(10, value.Scale));\n    }\n    public static explicit operator BigInteger(BigDecimal value)\n    {\n        return BigInteger.Divide(value._unscaledValue, BigInteger.Pow(10, value.Scale));\n    }\n    public static explicit operator xIntX(BigDecimal value)\n    {\n        return xIntX.Divide(value._unscaledValue, BigInteger.Pow(10, value.Scale));\n    }\n    public static explicit operator BigIntX(BigDecimal value)\n    {\n        return BigIntX.Divide(value._unscaledValue, BigInteger.Pow(10, value.Scale));\n    }\n    public static explicit operator float(BigDecimal value)\n    {\n        return (float)(double)value;\n    }\n    public static explicit operator double(BigDecimal value)\n    {\n        var factor = BigInteger.Pow(10, value.Scale);\n        if (SafeCastToDouble(value._unscaledValue) &amp;&amp; SafeCastToDouble(factor))\n            return (double)value._unscaledValue \/ (double)factor;\n        var dnv = value._unscaledValue * DoublePrecision \/ factor;\n        if (dnv.IsZero)\n            return value.Sign &lt; 0 ? BitConverter.Int64BitsToDouble(unchecked((long)0x8000000000000000)) : 0d;\n        double result   = 0;\n        var    isDouble = false;\n        var    scale    = 308;\n        while (scale > 0)\n        {\n            if (!isDouble)\n            {\n                if (SafeCastToDouble(dnv))\n                {\n                    result   = (double)dnv;\n                    isDouble = true;\n                }\n                else\n                {\n                    dnv \/= 10;\n                }\n            }\n            result \/= 10;\n            scale--;\n        }\n        if (!isDouble)\n            return value.Sign &lt; 0 ? double.NegativeInfinity : double.PositiveInfinity;\n        return result;\n    }\n    public static explicit operator decimal(BigDecimal value)\n    {\n        var factor = BigInteger.Pow(10, value.Scale);\n        if (SafeCastToDecimal(value._unscaledValue) &amp;&amp; SafeCastToDecimal(factor))\n            return (decimal)value._unscaledValue \/ (decimal)factor;\n        var dnv = value._unscaledValue * DecimalPrecision \/ factor;\n        if (dnv.IsZero)\n            return decimal.Zero;\n        for (var scale = 28; scale >= 0; scale--)\n            if (!SafeCastToDecimal(dnv))\n            {\n                dnv \/= 10;\n            }\n            else\n            {\n                var dec = new DecimalUInt32();\n                dec.dec   = (decimal)dnv;\n                dec.flags = (dec.flags &amp; ~0x00FF0000) | (scale &lt;&lt; 16);\n                return dec.dec;\n            }\n        throw new Exception(\"Value was either too large or too small for a Decimal.\");\n    }\n    public static implicit operator BigDecimal(sbyte value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(ushort value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(uint value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(ulong value)\n    {\n        return new BigDecimal((BigInteger)value);\n    }\n    public static implicit operator BigDecimal(byte value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(short value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(int value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(long value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(BigInteger value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(xIntX value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(BigIntX value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(float value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(double value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(decimal value)\n    {\n        return new BigDecimal(value);\n    }\n    public static implicit operator BigDecimal(BigRational value)\n    {\n        return new BigDecimal(value);\n    }\n    private static bool SafeCastToDouble(BigInteger value)\n    {\n        return DoubleMinValue &lt;= value &amp;&amp; value &lt;= DoubleMaxValue;\n    }\n    private static bool SafeCastToDecimal(BigInteger value)\n    {\n        return DecimalMinValue &lt;= value &amp;&amp; value &lt;= DecimalMaxValue;\n    }\n    private static BigInteger GetLastDigit(BigInteger value)\n    {\n        return value % new BigInteger(10);\n    }\n    private static int GetNumberOfDigits(BigInteger value)\n    {\n        return BigInteger.Abs(value).ToString().Length;\n    }\n    private static BigDecimal Factorial(BigDecimal x)\n    {\n        BigDecimal r = 1;\n        BigDecimal c = 1;\n        while (c &lt;= x)\n        {\n            r *= c;\n            c++;\n        }\n        return r;\n    }\n    public static BigDecimal Exp(BigDecimal x)\n    {\n        BigDecimal r  = 0;\n        BigDecimal r1 = 0;\n        var        k  = 0;\n        while (true)\n        {\n            r += Pow(x, k) \/ Factorial(k);\n            if (r == r1)\n                break;\n            r1 = r;\n            k++;\n        }\n        return r;\n    }\n    public static BigDecimal Sine(BigDecimal ar, int n)\n    {\n        if (Factorials == null)\n        {\n            Factorials = new BigDecimal[MaxFactorials];\n            for (var i = 0; i &lt; MaxFactorials; i++)\n                Factorials[i] = new BigDecimal(0, 0);\n            for (var i = 1; i &lt; MaxFactorials + 1; i++)\n                Factorials[i - 1] = Factorial(i);\n        }\n        var sin = ar;\n        for (var i = 1; i &lt;= n; i++)\n        {\n            var trm = Pow(ar, i * 2 + 1);\n            trm \/= Factorials[i * 2];\n            if ((i &amp; 1) == 1)\n                sin -= trm;\n            else\n                sin += trm;\n        }\n        return sin;\n    }\n    public static BigDecimal Atan(BigDecimal ar, int n)\n    {\n        var atan = ar;\n        for (var i = 1; i &lt;= n; i++)\n        {\n            var trm = Pow(ar, i * 2 + 1);\n            trm \/= i * 2;\n            if ((i &amp; 1) == 1)\n                atan -= trm;\n            else\n                atan += trm;\n        }\n        return atan;\n    }\n    public static BigDecimal Cosine(BigDecimal ar, int n)\n    {\n        if (Factorials == null)\n        {\n            Factorials = new BigDecimal[MaxFactorials];\n            for (var i = 0; i &lt; MaxFactorials; i++)\n                Factorials[i] = new BigDecimal(0, 0);\n            for (var i = 1; i &lt; MaxFactorials + 1; i++)\n                Factorials[i - 1] = Factorial(i);\n        }\n        BigDecimal cos = 1.0;\n        for (var i = 1; i &lt;= n; i++)\n        {\n            var trm = Pow(ar, i * 2);\n            trm \/= Factorials[i * 2 - 1];\n            if ((i &amp; 1) == 1)\n                cos -= trm;\n            else\n                cos += trm;\n        }\n        return cos;\n    }\n    public static BigDecimal GetE(int n)\n    {\n        BigDecimal e = 1.0;\n        var        c = n;\n        while (c > 0)\n        {\n            BigDecimal f = 0;\n            if (c == 1)\n            {\n                f = 1;\n            }\n            else\n            {\n                var i = c - 1;\n                f = c;\n                while (i > 0)\n                {\n                    f *= i;\n                    i--;\n                }\n            }\n            c--;\n            e += 1.0 \/ f;\n        }\n        return e;\n    }\n    public static BigDecimal Tangent(BigDecimal ar, int n)\n    {\n        return Sine(ar, n) \/ Cosine(ar, n);\n    }\n    public static BigDecimal CoTangent(BigDecimal ar, int n)\n    {\n        return Cosine(ar, n) \/ Sine(ar, n);\n    }\n    public static BigDecimal Secant(BigDecimal ar, int n)\n    {\n        return 1.0 \/ Cosine(ar, n);\n    }\n    public static BigDecimal NthRoot(BigDecimal value, int nth)\n    {\n        BigDecimal lx;\n        var        a = value;\n        var        n = nth;\n        BigDecimal s = 1.0;\n        do\n        {\n            var t = s;\n            lx = a \/ Pow(s, n - 1);\n            var r = (n        - 1) * s;\n            s = (lx + r) \/ n;\n        } while (lx != s);\n        return s;\n    }\n    public static BigDecimal LogN(BigDecimal value)\n    {\n        var        E = GetE(MaxFactorials);\n        BigDecimal a;\n        var        p = value;\n        BigDecimal n = 0.0;\n        while (p >= E)\n        {\n            p \/= E;\n            n++;\n        }\n        n += p \/ E;\n        p =  value;\n        do\n        {\n            a = n;\n            var lx = p         \/ Exp(n - 1.0);\n            var r  = (n - 1.0) * E;\n            n = (lx + r) \/ E;\n        } while (n != a);\n        return n;\n    }\n    public static BigDecimal Log(BigDecimal n, int b)\n    {\n        return LogN(n) \/ LogN(b);\n    }\n    public static BigDecimal CoSecant(BigDecimal ar, int n)\n    {\n        return 1.0 \/ Sine(ar, n);\n    }\n    public static BigDecimal Ceiling(BigDecimal value, int precision)\n    {\n        var v1 = new BigDecimal(value);\n        v1 = RemoveTrailingZeros(v1);\n        var diff = GetNumberOfDigits(v1._unscaledValue) - precision;\n        if (diff > 0)\n        {\n            for (var i = 0; i &lt; diff; i++)\n            {\n                v1._unscaledValue = BigInteger.Divide(v1._unscaledValue, 10);\n                v1.Scale--;\n            }\n            if (v1._unscaledValue.Sign &lt; 0)\n                v1._unscaledValue--;\n            else\n                v1._unscaledValue++;\n        }\n        return v1;\n    }\n    public static BigDecimal Floor(BigDecimal value, int precision)\n    {\n        var v1 = new BigDecimal(value);\n        v1 = RemoveTrailingZeros(v1);\n        var diff = GetNumberOfDigits(v1._unscaledValue) - precision;\n        if (diff > 0)\n        {\n            for (var i = 0; i &lt; diff; i++)\n            {\n                v1._unscaledValue = BigInteger.Divide(v1._unscaledValue, 10);\n                v1.Scale--;\n            }\n            if (v1._unscaledValue.Sign > 0)\n                v1._unscaledValue--;\n            else\n                v1._unscaledValue++;\n        }\n        return v1;\n    }\n    private static BigDecimal RemoveTrailingZeros(BigDecimal value)\n    {\n        var        v1 = new BigDecimal(value);\n        BigInteger remainder;\n        do\n        {\n            var shortened = BigInteger.DivRem(v1._unscaledValue, 10, out remainder);\n            if (remainder == BigInteger.Zero)\n            {\n                v1._unscaledValue = shortened;\n                v1.Scale--;\n            }\n        } while (remainder == BigInteger.Zero);\n        return v1;\n    }\n    public BigDecimal Min(BigDecimal value)\n    {\n        return CompareTo(value) &lt;= 0 ? this : value;\n    }\n    public BigDecimal Max(BigDecimal value)\n    {\n        return CompareTo(value) >= 0 ? this : value;\n    }\n    public static BigDecimal Sqrt(BigDecimal value)\n    {\n        return BigRational.Sqrt(value);\n    }\n    [StructLayout(LayoutKind.Explicit)]\n    internal struct DecimalUInt32\n    {\n        [FieldOffset(0)] public decimal dec;\n        [FieldOffset(0)] public int     flags;\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Arbitrary Precision Signed BigDecimal Updated: Jun-15,2021<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[112],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/213"}],"collection":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/comments?post=213"}],"version-history":[{"count":5,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/213\/revisions"}],"predecessor-version":[{"id":452,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/213\/revisions\/452"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=213"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=213"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=213"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}