Exemplo n.º 1
0
        public void Round(string result, string value, int decimals, MidpointRounding mode)
        {
            var resultDecimal = BigDecimal.Parse(result, CultureInfo.InvariantCulture);
            var valueDecimal  = BigDecimal.Parse(value, CultureInfo.InvariantCulture);

            Assert.Equal(resultDecimal, BigDecimal.Round(valueDecimal, decimals, mode));
        }
Exemplo n.º 2
0
        public SqlNumber Round(int precision)
        {
            if (State == NumericState.None)
            {
                return(new SqlNumber(innerValue.Round(new MathContext(precision, RoundingMode.HalfUp))));
            }

            return(this);
        }
Exemplo n.º 3
0
    public void TestTruncate()
    {
        const String inputTruncated =
            "0.38776413731534507341472294220970933835515664718260518542692164892369393388454765429965711304132864249950074173248631118139885711281403156400182208418498132380665348582256048635378814909035638369142648772177618951899185003568005598389270883746269077440991532220847404333505059368816860680653357748237545067181074698997348124273540082967040205337039719556204791774654186626822192852578297197622945023468587167940717672154626982847038945027431144177383552390076867181200131087852865589018597759807623800948540502708501473286123912110702619773244550322465985979980114779581215743799790210865866959716136152785422203785552850816565888483726280027736811701443283167094373785256268739306209472514414456698923382789454032363968616464876677737866600848986505927023714735496267888826964325695603484817243244809072199216323431074501911199589021095576091452848741385260278621154863084476153732935785975553768625991893151359011912157996422994871709298494233782632174324940552077998861058801035481527689611495569489001108047129667715138204276438217877458404549511313153150137527893798615996618488836664617057038126333313180040094667868763537391421370724952266262848120654117339947389714860375532634890853303061644123428823851175161042458377024247370039795707768407904842511280809838660155394320788005292339449327116941969519022963362256288633034183673183754543670394109495242494711094883817203892173617367313695468521390931623680173196403022932833410798171066411176995128779282872081932608267999112302172207922731784899893348412676098162467010668924433588685153611407005617772276741793479524433622378470125354022566116327819435029065557564148488746638319658731270457607183892425161850287824787546065413294231650473976473355046501500793677901782339691542233183741598103696583351788651177203938936918102755367072014549821942367309956671236707350861545099496206538228683951185018840006137763162355709495445928668480960580978979870379511703883251713690511544429859593313279574155504139941107166963497890833932811052504269372145803660626639428643564562691059910703703938694915154537936003382455188656514686359660013747580119285264755448830584594983111162605867224680013454700621697086948523549156403848856543212816956769085216390639154261614649538130954560421673680672884105498050605587531872704107707071402689983600332112655608194612408217782173036018661692139351433658340756975168361107372727516912020823362368253159826937134217107045868191298957690827125630453728790792408734840661702578638598543186544910552465999106381802375938701350575940262569041045146526024334627822715612658351899764042223444201035443823410277761971257862200600465373558428055133799307959576455801692979753194304758921759067399106319456847661528054181651013888120488047974670158855437555210689546049958555745098303660202886404313365902203237775035723926097742965028613593632230336269392684340085274710999024668887638930755250701806345477524832568256645103704878731032912768646402146422301881142289323523789305126831904241622042944333916620344863470012778933196413192781253025453531244850133026071231714118351386262249150472643870800725983523611903791303553632632769972142502483519860983067322477753824959399886980031912842700140970151007657989042261109130704991895244868527969247414974047405237324669264878742391500642753525622057641241164177505839173992651361990366480244195157062835803031557544691492841007028723179639729081951702197292799161437892952439082270465575308762112590993865133052593362045638622447863872110087219994330766670422412140283392118259566085972052360790645394540700438378734059789109046910356858343004387656915432928337709841252916626015752013241699464443045041876948902728601721842214670716585909801092203893128618468720651888522728597430373030188565238122801065278124235661294292641028550276301054915567825793810248724267437857461336921376742513529432313053995421425528496990787018582251366776291943999044323970133345610820834058391982655766601126736285624213085882525085728598384700565577250732861707158419417137322187913601105221450993534840307771350787020353312910993312574109077271828643659506792514058623896881407687463008239648545371730757776422468606770212802349464720937428992320859723193781752582479518699133569129895070994026410312951649922900688489934852155962598169718199217867461287501481443450777777718726084902136902441480397119384141792970385831367927360530354214563521320900336914169681532166791668676942898880184098720787172114194029069821244937592713815214434788393095503048740886117426353441330676447598548976011441527165748380891340472246800001389307364429687469295246232117792720007673578989468325170179570094184486525355114468774857635615955720968054081874458733938769018227387365842825259166694681823057556598910704367318366050815517174086712448729791746859581490981539042615521145996146036468018904747552880641671500884541141688250485043379587617571474356672696577799617797264760021142950373293666619603196041523466051054935554966409263947312788960948665394281916627352113060683470291466105925";
        const String inputOverflow = "919919200639429489197056";

        var expected = inputTruncated;

        var longValue = BigDecimal.Parse(String.Concat(inputTruncated, inputOverflow));
        var result    = BigDecimal.Round(longValue, 5000);

        var actual = result.ToString();

        Assert.AreEqual(expected, actual);
    }
Exemplo n.º 4
0
        public static BigDecimal Root(int n, BigDecimal x)
        {
            if (x.CompareTo(BigDecimal.Zero) < 0)
                throw new ArithmeticException("negative argument " + x + " of root");
            if (n <= 0)
                throw new ArithmeticException("negative power " + n + " of root");

            if (n == 1)
                return x;

            /* start the computation from a double precision estimate */
            var s = new BigDecimal(System.Math.Pow(x.ToDouble(), 1.0/n));

            /* this creates nth with nominal precision of 1 digit
                */
            var nth = new BigDecimal(n);

            /* Specify an internal accuracy within the loop which is
                * slightly larger than what is demanded by 'eps' below.
                */
            BigDecimal xhighpr = ScalePrecision(x, 2);
            var mc = new MathContext(2 + x.Precision);

            /* Relative accuracy of the result is eps.
                */
            double eps = x.Ulp().ToDouble()/(2*n*x.ToDouble());
            for (;;) {
                /* s = s -(s/n-x/n/s^(n-1)) = s-(s-x/s^(n-1))/n; test correction s/n-x/s for being
                        * smaller than the precision requested. The relative correction is (1-x/s^n)/n,
                        */
                BigDecimal c = xhighpr.Divide(s.Pow(n - 1), mc);
                c = s.Subtract(c);
                var locmc = new MathContext(c.Precision);
                c = c.Divide(nth, locmc);
                s = s.Subtract(c);
                if (System.Math.Abs(c.ToDouble()/s.ToDouble()) < eps)
                    break;
            }
            return s.Round(new MathContext(ErrorToPrecision(eps)));
        }
Exemplo n.º 5
0
        public static BigDecimal PowRound(BigDecimal x, Rational q)
        {
            /** Special cases: x^1=x and x^0 = 1
                */
            if (q.CompareTo(BigInteger.One) == 0)
                return x;
            if (q.Sign == 0)
                return BigDecimal.One;
            if (q.IsInteger) {
                /* We are sure that the denominator is positive here, because normalize() has been
                        * called during constrution etc.
                        */
                return PowRound(x, q.Numerator);
            }
            /* Refuse to operate on the general negative basis. The integer q have already been handled above.
                        */
            if (x.CompareTo(BigDecimal.Zero) < 0)
                throw new ArithmeticException("Cannot power negative " + x);
            if (q.IsIntegerFraction) {
                /* Newton method with first estimate in double precision.
                                * The disadvantage of this first line here is that the result must fit in the
                                * standard range of double precision numbers exponents.
                                */
                double estim = System.Math.Pow(x.ToDouble(), q.ToDouble());
                var res = new BigDecimal(estim);

                /* The error in x^q is q*x^(q-1)*Delta(x).
                                * The relative error is q*Delta(x)/x, q times the relative error of x.
                                */
                var reserr = new BigDecimal(0.5*q.Abs().ToDouble()
                                            *x.Ulp().Divide(x.Abs(), MathContext.Decimal64).ToDouble());

                /* The main point in branching the cases above is that this conversion
                                * will succeed for numerator and denominator of q.
                                */
                int qa = q.Numerator.ToInt32();
                int qb = q.Denominator.ToInt32();

                /* Newton iterations. */
                BigDecimal xpowa = PowRound(x, qa);
                for (;;) {
                    /* numerator and denominator of the Newton term.  The major
                                        * disadvantage of this implementation is that the updates of the powers
                                        * of the new estimate are done in full precision calling BigDecimal.pow(),
                                        * which becomes slow if the denominator of q is large.
                                        */
                    BigDecimal nu = res.Pow(qb).Subtract(xpowa);
                    BigDecimal de = MultiplyRound(res.Pow(qb - 1), q.Denominator);

                    /* estimated correction */
                    BigDecimal eps = nu.Divide(de, MathContext.Decimal64);

                    BigDecimal err = res.Multiply(reserr, MathContext.Decimal64);
                    int precDiv = 2 + ErrorToPrecision(eps, err);
                    if (precDiv <= 0) {
                        /* The case when the precision is already reached and any precision
                                                * will do. */
                        eps = nu.Divide(de, MathContext.Decimal32);
                    } else {
                        eps = nu.Divide(de, new MathContext(precDiv));
                    }

                    res = SubtractRound(res, eps);
                    /* reached final precision if the relative error fell below reserr,
                                        * |eps/res| < reserr
                                        */
                    if (eps.Divide(res, MathContext.Decimal64).Abs().CompareTo(reserr) < 0) {
                        /* delete the bits of extra precision kept in this
                                                * working copy.
                                                */
                        return res.Round(new MathContext(ErrorToPrecision(reserr.ToDouble())));
                    }
                }
            }
            /* The error in x^q is q*x^(q-1)*Delta(x) + Delta(q)*x^q*log(x).
                                * The relative error is q/x*Delta(x) + Delta(q)*log(x). Convert q to a floating point
                                * number such that its relative error becomes negligible: Delta(q)/q << Delta(x)/x/log(x) .
                                */
            int precq = 3 + ErrorToPrecision((x.Ulp().Divide(x, MathContext.Decimal64)).ToDouble()
                                             /System.Math.Log(x.ToDouble()));

            /* Perform the actual calculation as exponentiation of two floating point numbers.
                                */
            return Pow(x, q.ToBigDecimal(new MathContext(precq)));
        }
 public void RoundMathContextPrecision0()
 {
     String a = "3736186567876876578956958765675671119238118911893939591735";
     int aScale = 45;
     int precision = 0;
     RoundingMode rm = RoundingMode.HalfUp;
     MathContext mc = new MathContext(precision, rm);
     String res = "3736186567876.876578956958765675671119238118911893939591735";
     BigDecimal aNumber = new BigDecimal(BigInteger.Parse(a), aScale);
     BigDecimal result = aNumber.Round(mc);
     Assert.AreEqual(res, result.ToString(), "incorrect quotient value");
     Assert.AreEqual(aScale, result.Scale, "incorrect quotient scale");
 }