コード例 #1
0
ファイル: BigDecimal.cs プロジェクト: fronx/ioke
        public BigDecimal add(BigDecimal rhs,MathContext set)
        {
            BigDecimal lhs;
            int reqdig;
            BigDecimal res;
            sbyte[] usel;
            int usellen;
            sbyte[] user;
            int userlen;
            int newlen=0;
            int tlen=0;
            int mult=0;
            sbyte[] t=null;
            int ia=0;
            int ib=0;
            int ea=0;
            int eb=0;
            sbyte ca=0;
            sbyte cb=0;
            /* determine requested digits and form */
            if (set.lostDigits)
                checkdigits(rhs,set.digits);
            lhs=this; // name for clarity and proxy

            /* Quick exit for add floating 0 */
            // plus() will optimize to return same object if possible
            if (lhs.ind==0)
                if (set.form!=MathContext.PLAIN)
                    return rhs.plus(set);
            if (rhs.ind==0)
                if (set.form!=MathContext.PLAIN)
                    return lhs.plus(set);

            /* Prepare numbers (round, unless unlimited precision) */
            reqdig=set.digits; // local copy (heavily used)
            if (reqdig>0)
                {
                    if (lhs.mant.Length>reqdig)
                        lhs=clone(lhs).round(set);
                    if (rhs.mant.Length>reqdig)
                        rhs=clone(rhs).round(set);
                    // [we could reuse the new LHS for result in this case]
                }

            res=new BigDecimal(); // build result here

            /* Now see how much we have to pad or truncate lhs or rhs in order
               to align the numbers.  If one number is much larger than the
               other, then the smaller cannot affect the answer [but we may
               still need to pad with up to DIGITS trailing zeros]. */
            // Note sign may be 0 if digits (reqdig) is 0
            // usel and user will be the sbyte arrays passed to the adder; we'll
            // use them on all paths except quick exits
            usel=lhs.mant;
            usellen=lhs.mant.Length;
            user=rhs.mant;
            userlen=rhs.mant.Length;
                    if (lhs.exp==rhs.exp)
                        {/* no padding needed */
                            // This is the most common, and fastest, path
                            res.exp=lhs.exp;
                        }
                    else if (lhs.exp>rhs.exp)
                        { // need to pad lhs and/or truncate rhs
                            newlen=(usellen+lhs.exp)-rhs.exp;
                            /* If, after pad, lhs would be longer than rhs by digits+1 or
                               more (and digits>0) then rhs cannot affect answer, so we only
                               need to pad up to a length of DIGITS+1. */
                            if (newlen>=((userlen+reqdig)+1))
                                if (reqdig>0)
                                    {
                                        // LHS is sufficient
                                        res.mant=usel;
                                        res.exp=lhs.exp;
                                        res.ind=lhs.ind;
                                        if (usellen<reqdig)
                                            { // need 0 padding
                                                res.mant=extend(lhs.mant,reqdig);
                                                res.exp=res.exp-((reqdig-usellen));
                                            }
                                        return res.finish(set,false);
                                    }
                            // RHS may affect result
                            res.exp=rhs.exp; // expected final exponent
                            if (newlen>(reqdig+1))
                                if (reqdig>0)
                                    {
                                        // LHS will be max; RHS truncated
                                        tlen=(newlen-reqdig)-1; // truncation length
                                        userlen=userlen-tlen;
                                        res.exp=res.exp+tlen;
                                        newlen=reqdig+1;
                                    }
                            if (newlen>usellen)
                                usellen=newlen; // need to pad LHS
                        }
                    else{ // need to pad rhs and/or truncate lhs
                        newlen=(userlen+rhs.exp)-lhs.exp;
                        if (newlen>=((usellen+reqdig)+1))
                            if (reqdig>0)
                                {
                                    // RHS is sufficient
                                    res.mant=user;
                                    res.exp=rhs.exp;
                                    res.ind=rhs.ind;
                                    if (userlen<reqdig)
                                        { // need 0 padding
                                            res.mant=extend(rhs.mant,reqdig);
                                            res.exp=res.exp-((reqdig-userlen));
                                        }
                                    return res.finish(set,false);
                                }
                        // LHS may affect result
                        res.exp=lhs.exp; // expected final exponent
                        if (newlen>(reqdig+1))
                            if (reqdig>0)
                                {
                                    // RHS will be max; LHS truncated
                                    tlen=(newlen-reqdig)-1; // truncation length
                                    usellen=usellen-tlen;
                                    res.exp=res.exp+tlen;
                                    newlen=reqdig+1;
                                }
                        if (newlen>userlen)
                            userlen=newlen; // need to pad RHS
                    }

            if (lhs.ind==iszero)
                res.ind=ispos;
            else
                res.ind=lhs.ind; // likely sign, all paths
            if (((lhs.ind==isneg)?1:0)==((rhs.ind==isneg)?1:0))  // same sign, 0 non-negative
                mult=1;
            else {
                        mult=-1; // will cause subtract
                        /* Before we can subtract we must determine which is the larger,
                           as our add/subtract routine only handles non-negative results
                           so we may need to swap the operands. */

                                if (rhs.ind==iszero){
                                    // original A bigger
                                }else if ((usellen<userlen)|(lhs.ind==iszero))
                                    { // original B bigger
                                        t=usel;
                                        usel=user;
                                        user=t; // swap
                                        tlen=usellen;
                                        usellen=userlen;
                                        userlen=tlen; // ..
                                        res.ind=(sbyte)-res.ind; // and set sign
                                    }
                                else if (usellen>userlen){
                                    // original A bigger
                                }else{
                                    {/* logical lengths the same */ // need compare
                                        /* may still need to swap: compare the strings */
                                        ia=0;
                                        ib=0;
                                        ea=usel.Length-1;
                                        eb=user.Length-1;
                                        for(;;){
                                                if (ia<=ea)
                                                    ca=usel[ia];
                                                else
                                                    {
                                                        if (ib>eb)
                                                            {/* identical */
                                                                if (set.form!=MathContext.PLAIN)
                                                                    return ZERO;
                                                                // [if PLAIN we must do the subtract, in case of 0.000 results]
                                                                break;
                                                            }
                                                        ca=(sbyte)0;
                                                    }
                                                if (ib<=eb)
                                                    cb=user[ib];
                                                else
                                                    cb=(sbyte)0;
                                                if (ca!=cb)
                                                    {
                                                        if (ca<cb)
                                                            {/* swap needed */
                                                                t=usel;
                                                                usel=user;
                                                                user=t; // swap
                                                                tlen=usellen;
                                                                usellen=userlen;
                                                                userlen=tlen; // ..
                                                                res.ind=(sbyte)-res.ind;
                                                            }
                                                        break;
                                                    }
                                                /* mantissas the same, so far */
                                                ia++;
                                                ib++;
                                            }
                                    } // lengths the same
                                }
            }
            res.mant=byteaddsub(usel,usellen,user,userlen,mult,false);
            return res.finish(set,false);
        }
コード例 #2
0
ファイル: BigDecimal.cs プロジェクト: fronx/ioke
 public BigDecimal min(BigDecimal rhs,MathContext set)
 {
     if ((this.CompareTo(rhs,set))<=0)
         return this.plus(set);
     else
         return rhs.plus(set);
 }