示例#1
0
def evalf_log(expr, prec, options):
    arg = expr.args[0]
    workprec = prec + 10
    xre, xim, xacc, _ = evalf(arg, workprec, options)

    if xim:
        # XXX: use get_abs etc instead
        re = evalf_log(
            C.log(C.Abs(arg, evaluate=False), evaluate=False), prec, options)
        im = mpf_atan2(xim, xre or fzero, prec)
        return re[0], im, re[2], prec

    imaginary_term = (mpf_cmp(xre, fzero) < 0)

    re = mpf_log(mpf_abs(xre), prec, rnd)
    size = fastlog(re)
    if prec - size > workprec:
        # We actually need to compute 1+x accurately, not x
        arg = C.Add(S.NegativeOne, arg, evaluate=False)
        xre, xim, _, _ = evalf_add(arg, prec, options)
        prec2 = workprec - fastlog(xre)
        # xre is now x - 1 so we add 1 back here to calculate x
        re = mpf_log(mpf_abs(mpf_add(xre, fone, prec2)), prec, rnd)

    re_acc = prec

    if imaginary_term:
        return re, mpf_pi(prec), re_acc, prec
    else:
        return re, None, re_acc, None
示例#2
0
文件: evalf.py 项目: smichr/sympy
def evalf_log(expr, prec, options):
    arg = expr.args[0]
    workprec = prec + 10
    xre, xim, xacc, _ = evalf(arg, workprec, options)

    if xim:
        # XXX: use get_abs etc instead
        re = evalf_log(C.log(C.Abs(arg, evaluate=False), evaluate=False), prec, options)
        im = mpf_atan2(xim, xre or fzero, prec)
        return re[0], im, re[2], prec

    imaginary_term = mpf_cmp(xre, fzero) < 0

    re = mpf_log(mpf_abs(xre), prec, rnd)
    size = fastlog(re)
    if prec - size > workprec:
        # We actually need to compute 1+x accurately, not x
        arg = C.Add(S.NegativeOne, arg, evaluate=False)
        xre, xim, _, _ = evalf_add(arg, prec, options)
        prec2 = workprec - fastlog(xre)
        re = mpf_log(mpf_add(xre, fone, prec2), prec, rnd)

    re_acc = prec

    if imaginary_term:
        return re, mpf_pi(prec), re_acc, prec
    else:
        return re, None, re_acc, None
示例#3
0
def round(x, p=0):
    """Return x rounded to the given decimal place. If x is not an Expr,
    Python's round function is employed.

    Examples
    ========
    >>> from sympy import round, pi, S, Number
    >>> round(S(10.5))
    11.
    >>> round(pi)
    3.
    >>> round(pi, 2)
    3.14

    If x is not a SymPy Expr then Python's round is used and it returns
    a Python type, not a SymPy Number:

    >>> isinstance(round(543210, -2), Number)
    False
    >>> round(S(543210), -2)
    5.432e+5
    >>> _.is_Number
    True

    """
    from sympy.functions.elementary.exponential import log
    from sympy.mpmath.libmp import prec_to_dps

    if not isinstance(x, Expr):
        return _pyround(x, p)
    if not x.is_number:
        raise TypeError('%s is not a number' % x)
    if not x.is_real:
        raise TypeError("can't convert complex to int")
    if not x:
        return x
    p = int(p)

    precs = [f._prec for f in x.atoms(C.Float)]
    dps = prec_to_dps(max(precs)) if precs else None

    xpos = abs(x.n())
    try:
        mag_first_dig = int(ceil(log10(xpos)))
    except (ValueError, OverflowError):
        mag_first_dig = int(ceil(C.Float(mpf_log(xpos._mpf_, 53))/log(10)))
    # check that we aren't off by 1
    if (xpos/10**mag_first_dig) >= 1:
        mag_first_dig += 1
        assert .1 <= (xpos/10**mag_first_dig) < 1
    allow = digits_needed = mag_first_dig + p
    if dps is not None and allow > dps:
        allow = dps
    mag = Pow(10, p) # magnitude needed to bring digit p to units place
    x += 1/(2*mag) # add the half for rounding
    i10 = 10*mag*x.n((dps if dps is not None else digits_needed) + 1)
    rv = Integer(i10)//10
    q = 1
    if p > 0:
        q = mag
    elif p < 0:
        rv /= mag
    rv = Rational(rv, q)
    if rv.is_Integer:
        # use str or else it won't be a float
        return C.Float(str(rv), digits_needed)
    else:
        return C.Float(rv, allow)