'Evaluate the parts of self that are numbers; if the whole thing
was a number with no functions it would have been evaluated, but
it wasn\'t so we must judiciously extract the numbers and reconstruct
the object. This is *not* simply replacing numbers with evaluated
numbers. Nunmbers should be handled in the largest pure-number
expression as possible. So the code below separates ``self`` into
number and non-number parts and evaluates the number parts and
walks the args of the non-number part recursively (doing the same
thing).'

def _eval_evalf(self, prec):

    from .add import Add
    from .mul import Mul
    from .symbol import Symbol
    from .function import AppliedUndef
    if isinstance(self, (Mul, Add)):
        (x, tail) = self.as_independent(Symbol, AppliedUndef)
        if (not ((tail is self.identity) or (isinstance(x, AssocOp) and x.is_Function) or ((x is self.identity) and isinstance(tail, AssocOp)))):
            x = (x._evalf(prec) if (x is not self.identity) else self.identity)
            args = []
            tail_args = tuple(self.func.make_args(tail))
            for a in tail_args:
                newa = a._eval_evalf(prec)
                if (newa is None):
                    args.append(a)
                else:
                    args.append(newa)
            if (not _aresame(tuple(args), tail_args)):
                tail = self.func(*args)
            return self.func(x, tail)
    args = []
    for a in self.args:
        newa = a._eval_evalf(prec)
        if (newa is None):
            args.append(a)
        else:
            args.append(newa)
    if (not _aresame(tuple(args), self.args)):
        return self.func(*args)
    return self
