Repository: sympy/sympy

Issue:
simplify(x**2-x**2.0) does not yield 0.
bc.. >>> x**2.0-x**2
-x**2 + x**2.00000000000000

> > > simplify(x**2.0-x**2)
> > > -x**2 + x**2.00000000000000

This bug is related to bug 1274 .

p. Original issue for "#4473":https://github.com/sympy/sympy/issues/4473: "http://code.google.com/p/sympy/issues/detail?id=1374":http://code.google.com/p/sympy/issues/detail?id=1374

p. Original author: "https://code.google.com/u/107935137289803450816/":https://code.google.com/u/107935137289803450816/


Discussion:
sympy-bot: :white_check_mark:

Hi, I am the [SymPy bot](https://github.com/sympy/sympy-bot) (v147). I'm here to help you write a release notes entry. Please read the [guide on how to write release notes](https://github.com/sympy/sympy/wiki/Writing-Release-Notes).



Your release notes are in good order.

Here is what the release notes will look like:
* core
  - hash considers Floats in expressions != Rational equivalents while retaining numerical equivalence, so `x**2 != x**2.0` but `2 == 2.0` and the args of each will compare the same. ([#16770](https://github.com/sympy/sympy/pull/16770) by [@smichr](https://github.com/smichr))

  - comparison of Rational and Floats is more accurate ([#16770](https://github.com/sympy/sympy/pull/16770) by [@smichr](https://github.com/smichr))

  - `sympify` will not convert tuple and dict and respect requested keywords like `rational` when those are in such items ([#16770](https://github.com/sympy/sympy/pull/16770) by [@smichr](https://github.com/smichr))

  - `evalf` will detect when a Relational evaluates to True/False and return it instead of raising an error ([#16770](https://github.com/sympy/sympy/pull/16770) by [@smichr](https://github.com/smichr))

  - `nsimplify` will now accept more iterable containers ([#16770](https://github.com/sympy/sympy/pull/16770) by [@smichr](https://github.com/smichr))

This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.5.

Note: This comment will be updated with the latest check if you edit the pull request. You need to reload the page to see it. <details><summary>Click here to see the pull request description that was parsed.</summary>

    <!-- Your title above should be a short description of what
    was changed. Do not include the issue number in the title. -->

    #### References to other Issues or PRs
    <!-- If this pull request fixes an issue, write "Fixes #NNNN" in that exact
    format, e.g. "Fixes #1234". See
    https://github.com/blog/1506-closing-issues-via-pull-requests . Please also
    write a comment on that issue linking back to this pull request once it is
    open. -->
    closes #4473 `x**2 no longer equals x**2.0` but `2 == 2.0`
    closes #11707 
    closes #11708 as non-issue but improves handling of objects by sympify
    closes #16769 

    #### Brief description of what is fixed or changed

    An expression's hashable content now includes, as the leading entry, the number of floats in the expression since we don't want `x**2 == x**2.0`. Also, comparisons between Float and Rational were tightened up.

    This led to some failures in the core and I fixed those -- sometimes fixing other parts of code that were broken but didn't know it -- but the full suite tests show there are about 40+ other errors to look into.


    #### Other comments

    I could use some help correcting the following errors if the approach so far looks like it is going in the right direction:

    #### doctests
    - [ ] 0. doctest of approximants hangs
    #### tests
    - [ ] 1.
    ```
    ____ sympy/core/tests/test_args.py:test_sympy__physics__quantum__spin__CoupledSpinState 
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/tests/test_args.py", line 3309, in test_sympy__physics__quantum__spin__CoupledSpinState
        assert _test_args(CoupledSpinState(1, 0, (1, S(1)/2, S(1)/2)))
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/spin.py", line 1400, in __new__
        'in coupling number %d got j1,j2,j3: %d,%d,%d' % (n + 1, j1, j2, j3))
    ValueError: All couplings must have j1+j2 >= j3, in coupling number 1 got j1,j2,j3: 1,0,1
    ```
    - [ ] 2.
    ```
    ____ sympy/functions/special/tests/test_bsplines.py:test_5_points_degree_2 _____
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/functions/special/tests/test_bsplines.py", line 134, in test_5_points_degree_2
        spline = interpolating_spline(d, x, X, Y)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/functions/special/bsplines.py", line 259, in interpolating_spline
        basis = bspline_basis_set(d, knots, x)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/functions/special/bsplines.py", line 202, in bspline_basis_set
        return [bspline_basis(d, tuple(knots), i, x) for i in range(n_splines)]
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/functions/special/bsplines.py", line 202, in <listcomp>
        return [bspline_basis(d, tuple(knots), i, x) for i in range(n_splines)]
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/functions/special/bsplines.py", line 152, in bspline_basis
        b2 = bspline_basis(d - 1, knots, n + 1, x)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/functions/special/bsplines.py", line 163, in bspline_basis
        result = _add_splines(A, b1, B, b2)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/functions/special/bsplines.py", line 44, in _add_splines
        upper_2 = cond2.args[1].rhs
    AttributeError: 'And' object has no attribute 'rhs'
    ```
    - [ ] 3.
    ```
    ________ sympy/integrals/tests/test_transforms.py:test_hankel_transform ________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/integrals/tests/test_transforms.py", line 763, in test_hankel_transform
        assert hankel_transform(1/r, r, k, 0) == 1/k
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/integrals/transforms.py", line 1835, in hankel_transform
        return HankelTransform(f, r, k, nu).doit(**hints)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/integrals/transforms.py", line 1765, in doit
        **hints)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/integrals/transforms.py", line 1768, in _compute_transform
        return _hankel_transform(f, r, k, nu, self._name, **hints)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/integrals/transforms.py", line 204, in wrapper
        res = func(*args, **kwargs)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/integrals/transforms.py", line 1740, in _hankel_transform
        F = integrate(f*besselj(nu, k*r)*r, (r, 0, oo))
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/integrals/integrals.py", line 1487, in integrate
        return integral.doit(**doit_flags)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/integrals/integrals.py", line 635, in doit
        evalued = Add(*others)._eval_interval(x, a, b)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/expr.py", line 891, in _eval_interval
        B = limit(self, x, b,"-")
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/series/limits.py", line 82, in limit
        return Limit(e, z, z0, dir).doit(deep=False)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/series/limits.py", line 263, in doit
        r = gruntz(e, z, z0, dir)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/series/gruntz.py", line 646, in gruntz
        r = limitinf(e, z)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/series/gruntz.py", line 426, in limitinf
        c0, e0 = mrv_leadterm(e, x)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/series/gruntz.py", line 511, in mrv_leadterm
        series = calculate_series(f, w, logx=logw)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/series/gruntz.py", line 464, in calculate_series
        for t in e.lseries(x, logx=logx):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/expr.py", line 2785, in yield_lseries
        for si in s:
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/expr.py", line 2850, in _eval_lseries
        series = self._eval_nseries(x, n=n, logx=logx)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/mul.py", line 1637, in _eval_nseries
        terms = [t.nseries(x, n=n, logx=logx) for t in self.args]
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/mul.py", line 1637, in <listcomp>
        terms = [t.nseries(x, n=n, logx=logx) for t in self.args]
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/expr.py", line 2937, in nseries
        return self._eval_nseries(x, n=n, logx=logx)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/function.py", line 661, in _eval_nseries
        a = [t.compute_leading_term(x, logx=logx) for t in args]
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/function.py", line 661, in <listcomp>
        a = [t.compute_leading_term(x, logx=logx) for t in args]
    AttributeError: 'TupleArg' object has no attribute 'compute_leading_term'
    ```
    - [ ] 4.
    ```
    ________ sympy/calculus/tests/test_singularities.py:test_is_decreasing _________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/calculus/tests/test_singularities.py", line 66, in test_is_decreasing
        assert is_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3))
    AssertionError
    ```
    - [ ] 5.
    ```
    ____ sympy/calculus/tests/test_singularities.py:test_is_strictly_decreasing ____
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/calculus/tests/test_singularities.py", line 80, in test_is_strictly_decreasing
        assert is_strictly_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3))
    AssertionError
    ```
    - [ ] 6.
    ```
    ____________ sympy/calculus/tests/test_util.py:test_function_range _____________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/calculus/tests/test_util.py", line 35, in test_function_range
        ) == Interval(0, sqrt(5))
    AssertionError
    ```
    - [ ] 7.
    ```
    _____________ sympy/calculus/tests/test_util.py:test_not_empty_in ______________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/calculus/tests/test_util.py", line 84, in test_not_empty_in
        Union(Interval(S(3)/2, 2), FiniteSet(3))
    AssertionError
    ```
    - [ ] 8.
    ```
    ________ sympy/concrete/tests/test_sums_products.py:test_geometric_sums ________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/concrete/tests/test_sums_products.py", line 268, in test_geometric_sums
        assert result == 99999
    AssertionError
    ```
    - [ ] 9.
    ```
    ______________ sympy/core/tests/test_numbers.py:test_Rational_cmp ______________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/tests/test_numbers.py", line 390, in test_Rational_cmp
        assert n1 < n2
    AssertionError
    ```
    - [ ] 10.
    ```
    ______ sympy/functions/elementary/tests/test_piecewise.py:test_piecewise _______
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/functions/elementary/tests/test_piecewise.py", line 96, in test_piecewise
        assert p.evalf() == p
    AssertionError
    ```
    - [ ] 11.
    ```
    ____ sympy/functions/special/tests/test_gamma_functions.py:test_issue_14450 ____
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/functions/special/tests/test_gamma_functions.py", line 433, in test_issue_14450
        assert uppergamma(S(3)/8, x).evalf() == uppergamma(0.375, x)
    AssertionError
    ```
    - [ ] 12.
    ```
    ____________ sympy/geometry/tests/test_ellipse.py:test_issue_15797 _____________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/geometry/tests/test_ellipse.py", line 480, in test_issue_15797
        assert c.is_tangent(c.tangent_lines(A)[0]) == True
    AssertionError
    ```
    - [ ] 13.
    ```
    __________ sympy/geometry/tests/test_line.py:test_basic_properties_2d __________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/geometry/tests/test_line.py", line 198, in test_basic_properties_2d
        assert r.subs(x, -pi / 4) == Ray((0, 0), (1, -1))
    AssertionError
    ```
    - [ ] 14.
    ```
    ________________ sympy/geometry/tests/test_point.py:test_point _________________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/geometry/tests/test_point.py", line 106, in test_point
        Point(a.n(2), b.n(2))
    AssertionError
    ```
    - [ ] 15.
    ```
    _______________ sympy/geometry/tests/test_point.py:test_point3D ________________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/geometry/tests/test_point.py", line 184, in test_point3D
        Point(a.n(2), b.n(2))
    AssertionError
    ```
    - [ ] 16.
    ```
    ______________ sympy/geometry/tests/test_point.py:test_arguments _______________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/geometry/tests/test_point.py", line 354, in test_arguments
        assert a + (0.1, x) == Point(0.1, 1 + x)
    AssertionError
    ```
    - [ ] 17.
    ```
    ____________ sympy/geometry/tests/test_polygon.py:test_issue_12966 _____________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/geometry/tests/test_polygon.py", line 494, in test_issue_12966
        Point(5, 5), Point(10, 5), Point(10, 0), Point(5, 0)]
    AssertionError
    ```
    - [ ] 18.
    ```
    ___________ sympy/integrals/tests/test_integrals.py:test_issue_3664 ____________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/integrals/tests/test_integrals.py", line 297, in test_issue_3664
        2*cos(pi*n)/(pi*n)
    AssertionError
    ```
    - [ ] 19.
    ```
    _________ sympy/integrals/tests/test_transforms.py:test_sine_transform _________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/integrals/tests/test_transforms.py", line 688, in test_sine_transform
        assert sine_transform(1/sqrt(t), t, w) == 1/sqrt(w)
    AssertionError
    ```
    - [ ] 20.
    ```
    ________ sympy/integrals/tests/test_transforms.py:test_cosine_transform ________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/integrals/tests/test_transforms.py", line 725, in test_cosine_transform
        assert cosine_transform(1/sqrt(t), t, w) == 1/sqrt(w)
    AssertionError
    ```
    - [ ] 21.
    ```
    _____ sympy/ntheory/tests/test_egyptian_fraction.py:test_egyptian_fraction _____
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/ntheory/tests/test_egyptian_fraction.py", line 20, in test_egyptian_fraction
        [2, 6, 12, 35, 276, 2415]
    AssertionError
    ```
    - [ ] 22.
    ```
    ___________ sympy/physics/quantum/tests/test_density.py:test_entropy ___________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/tests/test_density.py", line 166, in test_entropy
        assert entropy(d) == 0.5*log(2)
    ```
    - [ ] 23.
    ```
     sympy/physics/quantum/tests/test_spin.py:test_uncouple_2_coupled_states_numerical 
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/tests/test_spin.py", line 984, in test_uncouple_2_coupled_states_numerical
        assert uncouple(JzKetCoupled(S(3)/2, S(3)/2, (1, S(1)/2))) ==   File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/spin.py", line 1400, in __new__
        'in coupling number %d got j1,j2,j3: %d,%d,%d' % (n + 1, j1, j2, j3))
    ValueError: All couplings must have j1+j2 >= j3, in coupling number 1 got j1,j2,j3: 1,0,1
    ```
    - [ ] 24.
    ```
     sympy/physics/quantum/tests/test_spin.py:test_uncouple_3_coupled_states_numerical 
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/tests/test_spin.py", line 1027, in test_uncouple_3_coupled_states_numerical
        assert uncouple(JzKetCoupled(S(3)/2, S(3)/2, (S(1)/2, S(1)/2, S(1)/2))) ==   File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/spin.py", line 1400, in __new__
        'in coupling number %d got j1,j2,j3: %d,%d,%d' % (n + 1, j1, j2, j3))
    ValueError: All couplings must have j1+j2 >= j3, in coupling number 2 got j1,j2,j3: 1,0,1
    ```
    - [ ] 25.
    ```
    ________ sympy/physics/quantum/tests/test_spin.py:test_couple_2_states _________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/tests/test_spin.py", line 1651, in test_couple_2_states
        assert JzKetCoupled(S(3)/2, S(3)/2, (1, S(1)/2)) ==   File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/spin.py", line 1400, in __new__
        'in coupling number %d got j1,j2,j3: %d,%d,%d' % (n + 1, j1, j2, j3))
    ValueError: All couplings must have j1+j2 >= j3, in coupling number 1 got j1,j2,j3: 1,0,1
    ```
    - [ ] 26.
    ```
    ________ sympy/physics/quantum/tests/test_spin.py:test_couple_3_states _________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/tests/test_spin.py", line 1706, in test_couple_3_states
        assert JzKetCoupled(S(3)/2, S(3)/2, (S(1)/2, S(1)/2, S(1)/2)) ==   File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/spin.py", line 1400, in __new__
        'in coupling number %d got j1,j2,j3: %d,%d,%d' % (n + 1, j1, j2, j3))
    ValueError: All couplings must have j1+j2 >= j3, in coupling number 2 got j1,j2,j3: 1,0,1
    ```
    - [ ] 27.
    ```
    ________ sympy/physics/quantum/tests/test_spin.py:test_couple_4_states _________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/tests/test_spin.py", line 1769, in test_couple_4_states
        assert JzKetCoupled(1, 1, (S(1)/2, S(1)/2, S(1)/2, S(1)/2)) ==   File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/spin.py", line 1400, in __new__
        'in coupling number %d got j1,j2,j3: %d,%d,%d' % (n + 1, j1, j2, j3))
    ValueError: All couplings must have j1+j2 >= j3, in coupling number 2 got j1,j2,j3: 1,0,1
    ```
    - [ ] 28.
    ```
    ___ sympy/physics/quantum/tests/test_spin.py:test_couple_2_states_numerical ____
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/tests/test_spin.py", line 1905, in test_couple_2_states_numerical
        JzKetCoupled(S(3)/2, S(3)/2, (1, S(1)/2))
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/spin.py", line 1400, in __new__
        'in coupling number %d got j1,j2,j3: %d,%d,%d' % (n + 1, j1, j2, j3))
    ValueError: All couplings must have j1+j2 >= j3, in coupling number 1 got j1,j2,j3: 1,0,1
    ```
    - [ ] 29.
    ```
    ___ sympy/physics/quantum/tests/test_spin.py:test_couple_3_states_numerical ____
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/tests/test_spin.py", line 1976, in test_couple_3_states_numerical
        3)/2, (S(1)/2, S(1)/2, S(1)/2), ((1, 2, 1), (1, 3, S(3)/2)) )
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/spin.py", line 1400, in __new__
        'in coupling number %d got j1,j2,j3: %d,%d,%d' % (n + 1, j1, j2, j3))
    ValueError: All couplings must have j1+j2 >= j3, in coupling number 2 got j1,j2,j3: 1,0,1
    ```
    - [ ] 30.
    ```
    ___ sympy/physics/quantum/tests/test_spin.py:test_couple_4_states_numerical ____
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/tests/test_spin.py", line 2801, in test_couple_4_states_numerical
        1)/2, S(1)/2, S(1)/2), ((1, 2, 1), (1, 3, S(3)/2), (1, 4, 2)) )
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/spin.py", line 1400, in __new__
        'in coupling number %d got j1,j2,j3: %d,%d,%d' % (n + 1, j1, j2, j3))
    ValueError: All couplings must have j1+j2 >= j3, in coupling number 2 got j1,j2,j3: 1,0,1
    ```
    - [ ] 31.
    ```
    __________ sympy/series/tests/test_approximants.py:test_approximants ___________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/series/tests/test_approximants.py", line 23, in test_approximants
        assert next(y) == -1/(t*(x + 1) - 1)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/series/approximants.py", line 69, in approximants
        s -= l[j+1] * m[b-j-1]
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/decorators.py", line 91, in __sympifyit_wrapper
        return func(a, b)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/decorators.py", line 129, in binary_op_wrapper
        return func(self, other)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/expr.py", line 142, in __sub__
        return Add(self, -other)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/operations.py", line 47, in __new__
        c_part, nc_part, order_symbols = cls.flatten(args)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/add.py", line 275, in flatten
        _addsort(newseq)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/add.py", line 21, in _addsort
        args.sort(key=_args_sortkey)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/basic.py", line 206, in compare
        st = self._hashable_content()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/basic.py", line 144, in _hashable_content
        return (self.count(Float),) + self._args
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/basic.py", line 1530, in count
        return sum(bool(query(sub)) for sub in preorder_traversal(self))
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/basic.py", line 1530, in <genexpr>
        return sum(bool(query(sub)) for sub in preorder_traversal(self))
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/basic.py", line 2020, in __next__
        return next(self._pt)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/basic.py", line 1991, in _preorder_traversal
        for subtree in self._preorder_traversal(arg, keys):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/basic.py", line 1991, in _preorder_traversal
        for subtree in self._preorder_traversal(arg, keys):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/basic.py", line 1991, in _preorder_traversal
        for subtree in self._preorder_traversal(arg, keys):
      [Previous line repeated 2 more times]
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/basic.py", line 1992, in _preorder_traversal
        yield subtree
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1303, in callback
        raise TimeOutError("Timed out after %d seconds" % timeout)
    sympy.utilities.runtests.TimeOutError: Timed out after 595 seconds
    ```
    - [ ] 32.
    ```
    ________ sympy/sets/tests/test_fancysets.py:test_ComplexRegion_contains ________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/numbers.py", line 1063, in __new__
        _mpf_ = num._as_mpf_val(precision)
    AttributeError: 'Mul' object has no attribute '_as_mpf_val'
    During handling of the above exception, another exception occurred:
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/sets/tests/test_fancysets.py", line 519, in test_ComplexRegion_contains
        assert 0.5 + 0.6*I in c3
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/sets/sets.py", line 555, in __contains__
        symb = sympify(self.contains(other))
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/sets/sets.py", line 287, in contains
        ret = sympify(self._contains(other))
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/sets/fancysets.py", line 1099, in _contains
        element.args[1]._contains(theta)):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/sets/sets.py", line 921, in _contains
        expr = And(expr, other < self.end)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/numbers.py", line 1338, in __lt__
        rv = self._Frel(other, mlib.mpf_lt)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/numbers.py", line 1315, in _Frel
        other = Float(other, self._prec)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/numbers.py", line 1065, in __new__
        _mpf_ = mpmath.mpf(num, prec=precision)._mpf_
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/mpmath/ctx_mp_python.py", line 77, in __new__
        v._mpf_ = mpf_pos(cls.mpf_convert_arg(val, prec, rounding), prec, rounding)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/mpmath/ctx_mp_python.py", line 96, in mpf_convert_arg
        raise TypeError("cannot create mpf from " + repr(x))
    TypeError: cannot create mpf from 2*pi
    ```
    - [ ] 33.
    ```
    ___________ sympy/simplify/tests/test_sqrtdenest.py:test_sqrtdenest3 ___________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/assumptions.py", line 244, in getit
        return self._assumptions[fact]
    KeyError: 'zero'
    During handling of the above exception, another exception occurred:
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/assumptions.py", line 244, in getit
        return self._assumptions[fact]
    KeyError: 'zero'
    During handling of the above exception, another exception occurred:
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/simplify/tests/test_sqrtdenest.py", line 100, in test_sqrtdenest3
        r7*(1 + r6 + r7)/(7*(sqrt(-2*r29 + 11) + r5)))
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/expr.py", line 695, in equals
        diff = factor_terms(simplify(self - other), radical=True)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/simplify/simplify.py", line 522, in simplify
        original_expr = expr = signsimp(expr)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/simplify/simplify.py", line 370, in signsimp
        e = sub_post(sub_pre(expr))
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/simplify/cse_opts.py", line 26, in sub_pre
        if a in reps or a.could_extract_minus_sign():
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/expr.py", line 2335, in could_extract_minus_sign
        (negative_self).extract_multiplicatively(-1) is not None)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/expr.py", line 2086, in extract_multiplicatively
        elif c == self:
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/numbers.py", line 2090, in __eq__
        return Rational.__eq__(self, other)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/numbers.py", line 1736, in __eq__
        if other.is_zero:
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/assumptions.py", line 248, in getit
        return _ask(fact, self)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/assumptions.py", line 303, in _ask
        _ask(pk, obj)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/assumptions.py", line 291, in _ask
        a = evaluate(obj)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/add.py", line 533, in _eval_is_imaginary
        if b.is_zero:
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/assumptions.py", line 248, in getit
        return _ask(fact, self)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/assumptions.py", line 303, in _ask
        _ask(pk, obj)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/assumptions.py", line 303, in _ask
        _ask(pk, obj)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/assumptions.py", line 291, in _ask
        a = evaluate(obj)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/add.py", line 597, in _eval_is_positive
        return super(Add, self)._eval_is_positive()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/core/expr.py", line 805, in _eval_is_positive
        if minimal_polynomial(self).is_Symbol:
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/polys/numberfields.py", line 654, in minimal_polynomial
        result = _minpoly_compose(ex, x, domain)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/polys/numberfields.py", line 533, in _minpoly_compose
        res = _minpoly_add(x, dom, *ex.args)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/polys/numberfields.py", line 364, in _minpoly_add
        mp = _minpoly_op_algebraic_element(Add, p, px, x, dom, mp1=mp)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/polys/numberfields.py", line 277, in _minpoly_op_algebraic_element
        _, factors = r.factor_list()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/polys/polytools.py", line 3240, in factor_list
        coeff, factors = f.rep.factor_list()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/polys/polyclasses.py", line 796, in factor_list
        coeff, factors = dmp_factor_list(f.rep, f.lev, f.dom)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/polys/factortools.py", line 1263, in dmp_factor_list
        return dup_factor_list(f, K0)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/polys/factortools.py", line 1212, in dup_factor_list
        coeff, factors = dup_zz_factor(f, K)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/polys/factortools.py", line 628, in dup_zz_factor
        H = dup_zz_zassenhaus(g, K)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/polys/factortools.py", line 328, in dup_zz_zassenhaus
        G = dup_mul(G, g[i], K)
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/polys/densearith.py", line 769, in dup_mul
        coeff += f[j]*g[i - j]
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1303, in callback
        raise TimeOutError("Timed out after %d seconds" % timeout)
    sympy.utilities.runtests.TimeOutError: Timed out after 595 seconds
    ```
    - [ ] 34.
    ```
    ___ sympy/physics/quantum/tests/test_spin.py:test_uncouple_2_coupled_states ____
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/tests/test_spin.py", line 592, in test_uncouple_2_coupled_states
        couple( TensorProduct(JzKet(S(1)/2, S(1)/2), JzKet(1, 1)) )))
    AssertionError
    ```
    - [ ] 35.
    ```
    ___ sympy/physics/quantum/tests/test_spin.py:test_uncouple_3_coupled_states ____
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/quantum/tests/test_spin.py", line 634, in test_uncouple_3_coupled_states
        S(1)/2, S(1)/2), JzKet(S(1)/2, S(1)/2), JzKet(S(1)/2, S(1)/2)) )))
    AssertionError
    ```
    - [ ] 36.
    ```
    _______ sympy/physics/tests/test_clebsch_gordan.py:test_clebsch_gordan5 ________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/tests/test_clebsch_gordan.py", line 213, in test_clebsch_gordan5
        assert clebsch_gordan(j_1, j_2, j, m_1, m_2, m) == 1
    AssertionError
    ```
    - [ ] 37.
    ```
    ______ sympy/physics/tests/test_hydrogen.py:test_hydrogen_energies_relat _______
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/tests/test_hydrogen.py", line 84, in test_hydrogen_energies_relat
        / sqrt(16*sqrt(3) + 32) - 4)) == 0
    AssertionError
    ```
    - [ ] 38.
    ```
    ______ sympy/physics/units/tests/test_util.py:test_convert_to_quantities _______
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/physics/units/tests/test_util.py", line 66, in test_convert_to_quantities
        assert convert_to(mile, kilometer) == 1.609344*kilometer
    AssertionError
    ```
    - [ ] 39.
    ```
    _____________ sympy/printing/tests/test_jscode.py:test_jscode_sqrt _____________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/printing/tests/test_jscode.py", line 23, in test_jscode_sqrt
        assert jscode(x**(S(1)/3)) == "Math.cbrt(x)"
    AssertionError
    ```
    - [ ] 40.
    ```
    ____ sympy/solvers/tests/test_inequalities.py:test_reduce_abs_inequalities _____
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/solvers/tests/test_inequalities.py", line 190, in test_reduce_abs_inequalities
        3*x - 5) < 7) == And(Lt(S(1)/2, x), Lt(x, 4))
    AssertionError
    ```
    - [ ] 41.
    ```
    __________ sympy/solvers/tests/test_inequalities.py:test_issue_10198 ___________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/solvers/tests/test_inequalities.py", line 384, in test_issue_10198
        And(S(0) < x, x < S(3)/4), And(S(3)/2 < x, x < oo))
    AssertionError
    ```
    - [ ] 42.
    ```
    ____________ sympy/solvers/tests/test_solveset.py:test_issue_10158 _____________
    Traceback (most recent call last):
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/solvers/tests/test_solveset.py", line 1763, in test_issue_10158
        assert solveset(Abs(x + 4*Abs(x + 1)), x, dom) == FiniteSet(-4/S(3), -4/S(5))
    AssertionError
    ```
    - [ ] 43.
    ```
    _____________ sympy/stats/tests/test_continuous_rv.py:test_uniform _____________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/stats/tests/test_continuous_rv.py", line 661, in test_uniform
        assert c(S(7)/2) == S(1)/4
    AssertionError
    ```
    - [ ] 44.
    ```
    _________________ sympy/utilities/tests/test_wester.py:test_L3 _________________
    Traceback (most recent call last):
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/runtests.py", line 1308, in _timeout
        function()
      File "/home/travis/virtualenv/python3.7.1/lib/python3.7/site-packages/sympy-1.5.dev0-py3.7.egg/sympy/utilities/tests/test_wester.py", line 816, in test_L3
        assert simplify((2**R(1, 3) + 4**R(1, 3))**3 - 6*(2**R(1, 3) + 4**R(1, 3)) - 6) == 0
    AssertionError
    ```
    #### Release Notes

    <!-- Write the release notes for this release below. See
    https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more information
    on how to write release notes. The bot will check your release notes
    automatically to see if they are formatted correctly. -->

    <!-- BEGIN RELEASE NOTES -->
    - core
        - hash considers Floats in expressions != Rational equivalents while retaining numerical equivalence, so `x**2 != x**2.0` but `2 == 2.0` and the args of each will compare the same.
        - comparison of Rational and Floats is more accurate
        - `sympify` will not convert tuple and dict and respect requested keywords like `rational` when those are in such items
        - `evalf` will detect when a Relational evaluates to True/False and return it instead of raising an error
        - `nsimplify` will now accept more iterable containers
    <!-- END RELEASE NOTES -->


</details><p>

asmeurer: I'm not sure if this behavior makes sense

```py
>>> S(2.0) == S(2)
True
>>> x + S(2.0) == x + S(2)
False
```

Shouldn't we have both true or both false? I'm leaning toward both true, since Float(2.0) is exactly equal to Integer(2) as a rational number.
asmeurer: I like the other changes here, though, especially the more stringent float comparison that makes `0.1 == Rational(1, 10)` give False. That's actually a big first step to fixing #11707. I would suggest splitting them off. It may also make the tests easier to fix. I'm guessing some are due to more stringent float comparison and some are due to disallowing floats to equal rationals inside of expressions.

Also even if we do keep the changes here as is, I don't think this completely fixes #11707. 

```
>>> Float("0.1") == Rational(Float("0.1"))
True
>>> hash(Float("0.1")) == hash(Rational(Float("0.1")))
False
```

We need the hash algorithm discussed in the issue, so that numerically equal numbers give the same hashes. Alternately Rational == Float should never be true, but I think that needs more discussion if we chose that route. 
smichr: working on fixing some errors
jksuom: > Rational == Float should never be true

I am beginning to believe that this is how it should be. A Float, represented by a rational number (an integral multiple of a power of 2), denotes a real number in an interval determined by precision. (The endpoints of the interval are also rational numbers.) `Rational == Float` could be None if the rational number falls within that interval, otherwise it should be false.
oscarbenjamin: The issue with Rational != Float is transitivity:
```
S(2) == 2 == 2.0 == S(2.0)
```
Perhaps a way to break that chain would be if 2.0 != S(2.0).
smichr: > `Rational == Float` could be None

Doesn't `==` have to give True or False?
smichr: > We need the hash algorithm discussed in the issue, so that numerically equal numbers give the same hashes.

I just implemented exact comparisons but Float can still equal Rational.

I can't see a way to implement "equal numbers => equal hash", however. `Float(.5, 1) == Float(.5, 2) == 1/2` but they each have a different hash. To give them the same hash would require 

1) leaving off the precision information for the Floats -- but then does that mean that cache will use in calculations whichever came first? and 
1) store fractions with power-of-2 denominators like mpfs with infinite precision.

This would imply that we can only do `Float(.5, 1) != Float(.5, 2)` and `Float != Rational`. And there would be some justification in that: numbers with different don't behave the same (and from a real-world perspective even "cost" more as the precision increases) and a Rational represents an ideal...so they really are 3 different things.
jksuom: > store fractions with power-of-2 denominators like mpfs with infinite precision

It looks like that Python does something like this when identifying floats with (some) rationals. That makes arithmetic laws dependent on the type of the operands.
```
>>> a = 1<<53
>>> b = float(a)
>>> a == b
True
>>> a + 1 == b + 1
False
```
I personally would prefer preservation of mathematical properties (as far as possible) even if that would make == not imply equal hash.
smichr: > imply equal hash

I see that the precision was added to the hashable content [in this commit](https://github.com/sympy/sympy/commit/769b0489ca020facb7d942a63076d2b4bafc8253). What happens if we take out that part of the hash besides? Would this mean that the unintended higher precision value might be used in a calculation? Decimal hashes different precisions to the same value so there must be a way around this issue. Maybe they don't cache their numbers?
oscarbenjamin: > I personally would prefer preservation of mathematical properties (as far as possible) even if that would make == not imply equal hash.

We need `a==b implies hash(a)==hash(b)` if sympified objects are to work properly in sets and dicts. This is explained in the docs:
https://docs.python.org/3.3/reference/datamodel.html#object.__hash__
The implementation of hash table data structures depends on the contrapositive `hash(a)!=hash(b) implies a!=b` to function correctly. Not respecting that will cause obscure and hard to track down problems. This is the sole purpose of `__hash__` so there is no point in defining it any other way.

The other constraint on this is that currently SymPy allows free interoperation with Python's int/float types. That in turn means that SymPy's `__eq__` needs to be consistent with theirs. If we said that `S(2)!=2` and `S(2.0)!=2.0` then we could freely defined `__eq__` for SymPy objects to do something different from what Python does for int/float.

If SymPy's `__eq__` is consistent with Python's then we can just use `fractions.__hash__` for all rational numbers (including normal Floats etc):
https://github.com/python/cpython/blob/c664b342a47e4b4650706d07e3e40a295e3a4407/Lib/fractions.py#L548

Python's Decimal type does hash floats with different precision to the same value but that's necessary because they compare equal:
```
In [27]: from decimal import Decimal                                                                                              

In [28]: d1 = Decimal('3.0')                                                                                                      

In [29]: d2 = Decimal('3.00000000000000')                                                                                         

In [30]: d1                                                                                                                       
Out[30]: Decimal('3.0')

In [31]: d2                                                                                                                       
Out[31]: Decimal('3.00000000000000')

In [32]: d1 == d2                                                                                                                 
Out[32]: True
```
Perhaps the difference is that the decimal library attaches actual working precision for calculations not to the Decimal instance but to the context in place at the time of the calculation:
```
In [36]: Decimal('2') / Decimal('3.00000')                                                                                        
Out[36]: Decimal('0.6666666666666666666666666667')
```
jksuom: >  if sympified objects are to work properly in sets and dicts

I think that this should apply to sympified objects that can be used *interchangeably* anywhere, like two Floats that have the same `_mpf_` and `_prec`. But I am not sure that it would make sense to allow replacing e.g. Integer(2) freely with Float(2) even though == would be true.
oscarbenjamin: > > if sympified objects are to work properly in sets and dicts
> 
> I think that this should apply to sympified objects that can be used _interchangeably_ anywhere, like two Floats that have the same `_mpf_` and `_prec`. But I am not sure that it would make sense to allow replacing e.g. Integer(2) freely with Float(2) even though == would be true.

Internally dicts/sets use `__eq__` as well as `__hash__`. The precise implementation varies across Python versions and implementations (i.e. pypy but also significant changes in recent CPython releases). Breaking the hash invariant leads to undefined behaviour and is not a supported or reliable way of ensuring that objects that compare equal are distinguished by hash-based containers. For example what happens when there's a hash collision?

If we want objects to be treated as distinct keys in e.g. a dict then the correct way to do that is to store keys that compare unequal with `__eq__`. Making the hashes also unequal can speed up dict lookup but is not essential for correctness.

We could add an attribute/method `_as_tuple` or `_cache_key` to `Basic` that returns something like a `(func, args)` tuple with the args also recursively tuplified. That could be used as a key for a caches etc. since that would only compare equal when two objects really are the same kind of SymPy object e.g.
```
>>> S(1)._as_tuple
(Integer, 1)
>>> S(1.0).as_tuple
(Float, ((0, 1, 0, 1), 53))
>>> exp(2)._as_tuple
(exp, ((Integer, 2),))
```
asmeurer: Reminder that I've written about what can happen when a == b doesn't imply hash(a) == hash(b) https://www.asmeurer.com/blog/posts/what-happens-when-you-mess-with-hashing-in-python/. The example 3 behavior can be seen with Rational and Float in master (see the example at the top of https://github.com/sympy/sympy/issues/11707).
asmeurer: I disagree with the notion that floating point numbers should be considered as intervals. It's better to think of floating point numbers (at some given precision n) as a subset of the rational numbers. The particular numbers which constitute that set is determined by n and the semantics of mpf, but just consider that there is *some* subset of rational numbers which are also floating point numbers (ignore infinity and nan; they don't matter for this discussion). Any arithmetic of numeric function on floating point numbers should produce the value in the set that is closest to the true mathematical value. One may also consider the "identity" function that maps a rational number to its closest floating point equivalent, for instance, `1.1 -> 2476979795053773*2**-51` (for the default binary precision 53).

The distinction is important. It's not the floating point numbers themselves that are inexact, but rather the arithmetic and numeric functions. Every floating point number is an exact rational number. However, not every rational number is a valid floating point number (for a given precision n), and must be mapped to the closest approximation when encountered, either as direct input from the user (`1.1`), or as the result of a numeric or arithmetic operation. To quote http://mpmath.org/doc/current/technical.html:

> Contrary to popular belief, floating-point numbers do not come with an inherent “small uncertainty”, although floating-point arithmetic generally is inexact. Every binary floating-point number is an exact rational number. With arbitrary-precision integers used for the mantissa and exponent, floating-point numbers can be added, subtracted and multiplied exactly. In particular, integers and integer multiples of 1/2, 1/4, 1/8, 1/16, etc. can be represented, added and multiplied exactly in binary floating-point arithmetic.
smichr: > I disagree with the notion that floating point numbers should be considered as intervals. It's better to think of floating point numbers (at some given precision n) as a subset of the rational numbers.

Yes, I think we agree. But for purposes of testing -- not at the `__eq__/hash` level, however -- it is useful to think of two numbers being as good as equal if the Rational falls within the limits of representation of the Float against which it is being compared. I understand that this is *not* what is under consideration.

I have added a commit where I attempt to get equivalent Float and Rational hashing to the same values. All exact base-2 fractions (Integer, Float and some Rational) will all store an mpf as their hashable content while other Rationals will store their (p,q) tuple.
jksuom: > Every floating point number is an exact rational number.

I would rather say that a floating point number is *represented* by an exact rational number. I don't think that they could be the same because their arithmetic properties are different. Moreover, there is a whole series of SymPy Floats of different precision represented by a single rational number. We should be able to distinguish between them when precision is changed in the course of a computation. Can that be done using `__eq__`?
smichr: > Can that be done using `__eq__`?

If we let `2 == 2.0` then, like Decimal, I think we have to let `Float(2, 15) == Float(2, 100)`.
smichr: Despite the comment in `Basic.__eq__` I don't know how to set this up with `__hash__` or `_hashable_content` so `hash(Float(3)) == hash(Integer(3))`. I think I have the `_hash` values sorted out, however: `Rational(a/2**b)` stores an `mpf` while other `Rational`s store `(p, q)`; `Float(int)` stores an `int` else an `mpf`.
oscarbenjamin: > > Every floating point number is an exact rational number.
> 
> I would rather say that a floating point number is _represented_ by an exact rational number. I don't think that they could be the same because their arithmetic properties are different. Moreover, there is a whole series of SymPy Floats of different precision represented by a single rational number. We should be able to distinguish between them when precision is changed in the course of a computation. Can that be done using `__eq__`?

I agree with what you are saying but there are a series of design decisions in Python and SymPy that lead to the conclusion that Float precision needs to be ignored by `__eq__` (and `__hash__`). From SymPy's perspective this stems from the decision to have S(2)==2 and S(2.0)==2.0.

The overarching conflict here is that SymPy is implemented not just on top of Python but also to be used from within Python and to interoperate seamlessly with Python's existing types. If we were building something on top of Python with users writing their code in another language then there would be no need to allow Python's int/float to be mixed into any operations with SymPy types and we would be free to define these things however we liked. We could define one == to be used from Python code that really does do structural equality and another == for users to use (in the user language) that does mathematical equality.

For caching in particular this can be solved by not using a SymPy object directly as the cache key. Likewise in other situations where we use == but want to distinguish Floats with different precision or Float from Integer etc we could define a method/function or use some other key to achieve whatever effect is wanted in comparing the objects.
oscarbenjamin: > I think I have the _hash values sorted out, however: Rational(a/2**b) stores an mpf while other Rationals store (p, q); Float(int) stores an int else an mpf.

Would it not make sense to put this in `Number.__hash__` and use as_numer_denom?
smichr: Float  `as_numer_denom()` self gives (self, 1).

More importantly, in order to match Python we have to use has(self.p) when self equals an int.
asmeurer: Precision does complicate things a bit. If we use my idea of only thinking about the numeric value of a float for equality, and not its arithmetical properties, then the precision should be ignored, since it only affects the arithmetic properties. `Float('2.0', 2)` and `Float('2.0', 15)` both represent the exact same rational number (the `_mpf_` in both cases is `(0, 1, 1, 1)`, corresponding to `1*2**1`). The difference is that the former is a member of a smaller subset of rationals, so the truncation after operations will be different, e.g., `2.0 + 0.01`. 

I do worry about the effect of ignoring type (`Rational` vs. `Float`) and precision on the cache. Will the cache swap out floats for equivalent rationals, or two equal floats with unequal precisions? If so, this may be a larger concern than keeping transitivity with Python numbers (I actually don't think transitivity is that important, although `2 != 2.0` will be unexpected by most users, and `S(2) != int(2)` will be even more unexpected). Storing the type along with the value in the cache could solve the issue for Rational/Float, and it's probably a good idea anyway. I think most SymPy classes would suffer the same issue when subclassed without modifying their args. But that doesn't take care of precision. I wish there were a clever way to incorporate the precision into the hash. But if we want to use the same has as Python, so that `a == b -> hash(a) == hash(b)` if `a` is a SymPy Float/Rational and `b` is a Python int/float, then we have to use the same numeric hash algorithm as Python. I don't see how we can incorporate the precision into that. 
oscarbenjamin: Storing the type along with the object won't help if the object is not a simple Float/Rational e.g. `cos(2*x)` vs `cos(2.0*x)`.

Loss of transitivity means that the contents of `set(items)` can have different numbers of elements depending on the order of items. In Python we have
```python
>>> {2, 2.0}
{2}
>>> {2.0, 2}
{2.0}
```
What happens is that `__eq__` defines an equivalence class. The set contains exactly one element representing each equivalence class which is simply the first one encountered. In building the above sets once 2 or 2.0 has been added the other is not since it is equal to something already in the set.

We can define an Integer class that breaks transitivity by only comparing equal to int and not float like so:
```python
class Integer(object):
    '''
    Integer class that compares equal to int but not float.
    '''
    def __init__(self, num):
        self.num = num

    def __repr__(self):
        return 'Integer(%d)' % (self.num,)

    def __eq__(self, other):
        if isinstance(other, Integer):
            return self.num == other.num
        elif isinstance(other, int):
            return self.num == other
        elif isinstance(other, float):
            return False
        return NotImplemented

    def __hash__(self):
        return hash(self.num)
```
Then if we create sets that mix this with ints/floats we get:
```python
>>> from tmp import Integer
>>> {2, 2.0, Integer(2)}
{2}
>>> {2.0, Integer(2), 2}
{2.0, Integer(2)}
```
Now the number of items in the set depends on the order of the inputs. This is because the `__eq__` we have defined does not properly define equivalence classes by not satisfying transitivity.
smichr: The hashing algorithm for Decimal (which is said to give the same value as for float, but I didn't check) is given [here](https://www.quora.com/How-does-Pythons-built-in-hash-function-work):

```python
def __hash__(self):
        """x.__hash__() <==> hash(x)"""
        # Decimal integers must hash the same as the ints
        #
        # The hash of a nonspecial noninteger Decimal must depend only
        # on the value of that Decimal, and not on its representation.
        # For example: hash(Decimal('100E-1')) == hash(Decimal('10')).
        if self._is_special:
            if self._isnan():
                raise TypeError('Cannot hash a NaN value.')
            return hash(str(self))
        if not self:
            return 0
        if self._isinteger():
            op = _WorkRep(self.to_integral_value())
            # to make computation feasible for Decimals with large
            # exponent, we use the fact that hash(n) == hash(m) for
            # any two nonzero integers n and m such that (i) n and m
            # have the same sign, and (ii) n is congruent to m modulo
            # 2**64-1.  So we can replace hash((-1)**s*c*10**e) with
            # hash((-1)**s*c*pow(10, e, 2**64-1).
            return hash((-1)**op.sign*Page on Op*pow(10, op.exp, 2**64-1))
        # The value of a nonzero nonspecial Decimal instance is
        # faithfully represented by the triple consisting of its sign,
        # its adjusted exponent, and its coefficient with trailing
        # zeros removed.
        return hash((self._sign,
                     self._exp+len(self._int),
                     self._int.rstrip('0')))
```
jksuom: It seems that this is the old implementation. The [new version](https://github.com/python/cpython/blob/ad4ed872415d00fcdfaa52a08108ec752b115000/Lib/_pydecimal.py#L939-L963) looks compatible with the new implementation for ints and floats (no more the hash of a triple (sign, exp, int)). There is also a C-version in Modules/_decimal/_decimal.c but that appears much harder to read.
jksuom: Python Decimal is analogous to SymPy Float in that both have arbitrary precision. A fundamental difference (apart from different base) is that Decimal has no precision attribute. Instead, there is a global context that includes user adjustable precision. There is no problem with equality and hash as precision need not be considered. The arithmetic operations depend on the context. Maybe a context could also be implemented in SymPy core (and the precision of Floats deprecated).
smichr: It doesn't look like Decimal tries to match hash with float (though it does with int):
```python
>>> hash(Decimal('12.57')),hash(12.57)
(1481763729, 1997161115)
>>> hash(Decimal('12.')),hash(12.)
(12, 12)
>>> Decimal('12.57')==12.57
False
```
jksuom: float(12.57) cannot be represented exactly by a decimal fraction, Fraction has to be used (and Python 3 for the new hash).
```
>>> hash(Fraction(1257, 100))
2144433998568735387
>>> hash(Decimal('12.57'))
2144433998568735387
>>> Decimal('12.57') == Fraction(1257, 100)
True
```
Multiples of negative powers of 2 can be exactly represented by floats.
```
>>> Decimal('12.25') == 12.25
True
>>> Fraction(1225, 100) == 12.25
True
```
asmeurer: The Python hash algorithm is described here https://docs.python.org/3/library/stdtypes.html#hashing-of-numeric-types. I don't know if it can be be implemented more efficiently for float, since the denominator is always a power of 2 (it seems the built-in `pow` doesn't accept negative exponents with the third argument). I also don't know if it is already implemented in mpmath, but if it is, we should use that (assuming we do decide on this algorithm). 
smichr: @jksuom , thanks for looking this over. I'm glad I currently have a schedule that can permit this and that the weather outside has been inclining toward winter again! This has been a real slog. Several of the other changes are motivated by the subtle change in how things are compared -- or, perhaps more likely, in my ignorance about how fragile some of the current code really is. Your input is a great encouragement as always.
smichr: So do we have one exception to the `Float != Rational` rule: `0.0 == 0`? If not, probably all `foo == 0` need to be reviewed and perhaps replaced with `foo.is_zero`. And then maybe `1/0.0` giving `oo` but `1/0` giving `zoo` makes sense?
jksuom: As to the Float != Rational rule, it seems that no decision was made so far. I think that letting a Float be equal to its representing rational number n/2**k could be a viable alternative. Then some Floats with different precision would be equal but Python is able to handle Decimals ignoring precision.

In any case, I think that `0.0 == 0` could be true. One reason is that "zero is zero at any precision", i.e., there is only one floating point zero and its arithmetic properties are the same as those of S.Zero. That would make `1/0.0` equal to `zoo` which I think is a better choice than `oo` or `-oo`. Those are one-sided limits along the real line and there is no preferred direction in `1/0.0`.
jksuom: > We need the hash algorithm discussed in the issue, so that numerically equal numbers give the same hashes. Alternately Rational == Float should never be true, but I think that needs more discussion if we choose that route.

I think that a Python compatible hash algorithm could be easily implemented. (And it would not be necessary to have always Rational != Float.)

Integer hash could be simply `hash(p)`. It could also be coded explicitly on Python 3 but the native implementation is more efficient as it is in C. In addition, Python 2 implementation is different and harder to reproduce in python.

For Float hash we could use `mpf_hash`. It looks compatible with floats and with Fractions whose denominator is a power of 2 on Python 3. It may not be fully compatible with Fractions on Python 2, but that is going to be dropped anyway.

For Rational, `hash(Fraction(p, q))` looks like the best implementation. That should work for both Python 2 and 3. There is a minor overhead as Fraction tries to reduce the representation. When the support for Python 2 is dropped, it is possible to copy the (concise) implementation of `Fraction.__hash__` with no need for reduction.
codecov[bot]: # [Codecov](https://codecov.io/gh/sympy/sympy/pull/16770?src=pr&el=h1) Report
> Merging [#16770](https://codecov.io/gh/sympy/sympy/pull/16770?src=pr&el=desc) into [master](https://codecov.io/gh/sympy/sympy/commit/8e4de91a1c958526e4dc0cfbc671a12b114b8b0d?src=pr&el=desc) will **decrease** coverage by `18.215%`.
> The diff coverage is `78.947%`.

```diff
@@              Coverage Diff               @@
##            master    #16770        +/-   ##
==============================================
- Coverage   73.849%   55.634%   -18.216%     
==============================================
  Files          619       619                
  Lines       159759    159772        +13     
  Branches     37489     37500        +11     
==============================================
- Hits        117982     88889     -29093     
- Misses       36319     65080     +28761     
- Partials      5458      5803       +345
```

smichr: ping @asmeurer , @jksuom . It looks like this is going to be passing now. branch name not withstanding, I really don't want to get into the hash changes. Do we have a consensus for the current changes?
asmeurer: I'll try to take a look if I get a chance. This touches a lot of core code, so it may be worth checking benchmarks to see if there are any regressions. 

Patch:
diff --git a/sympy/core/basic.py b/sympy/core/basic.py
index 8318066531..3fc12ecc48 100644
--- a/sympy/core/basic.py
+++ b/sympy/core/basic.py
@@ -1883,21 +1883,28 @@ def _aresame(a, b):
     Examples
     ========
 
-    To SymPy, 2.0 == 2:
+    In SymPy (as in Python) two numbers compare the same if they
+    have the same underlying base-2 representation even though
+    they may not be the same type:
 
     >>> from sympy import S
     >>> 2.0 == S(2)
     True
+    >>> 0.5 == S.Half
+    True
 
-    Since a simple 'same or not' result is sometimes useful, this routine was
-    written to provide that query:
+    This routine was written to provide a query for such cases that
+    would give false when the types do not match:
 
     >>> from sympy.core.basic import _aresame
     >>> _aresame(S(2.0), S(2))
     False
 
     """
+    from .numbers import Number
     from .function import AppliedUndef, UndefinedFunction as UndefFunc
+    if isinstance(a, Number) and isinstance(b, Number):
+        return a == b and a.__class__ == b.__class__
     for i, j in zip_longest(preorder_traversal(a), preorder_traversal(b)):
         if i != j or type(i) != type(j):
             if ((isinstance(i, UndefFunc) and isinstance(j, UndefFunc)) or
diff --git a/sympy/core/expr.py b/sympy/core/expr.py
index aeb95bbd05..87a5c91350 100644
--- a/sympy/core/expr.py
+++ b/sympy/core/expr.py
@@ -681,6 +681,7 @@ def equals(self, other, failing_expression=False):
         """
         from sympy.simplify.simplify import nsimplify, simplify
         from sympy.solvers.solveset import solveset
+        from sympy.solvers.solvers import solve
         from sympy.polys.polyerrors import NotAlgebraic
         from sympy.polys.numberfields import minimal_polynomial
 
@@ -707,15 +708,19 @@ def equals(self, other, failing_expression=False):
         if constant is False:
             return False
 
-        if constant is None and not diff.is_number:
-            # e.g. unless the right simplification is done, a symbolic
-            # zero is possible (see expression of issue 6829: without
-            # simplification constant will be None).
-            return
+        if not diff.is_number:
+            if constant is None:
+                # e.g. unless the right simplification is done, a symbolic
+                # zero is possible (see expression of issue 6829: without
+                # simplification constant will be None).
+                return
 
         if constant is True:
+            # this gives a number whether there are free symbols or not
             ndiff = diff._random()
-            if ndiff:
+            # is_comparable will work whether the result is real
+            # or complex; it could be None, however.
+            if ndiff and ndiff.is_comparable:
                 return False
 
         # sometimes we can use a simplified result to give a clue as to
@@ -723,47 +728,67 @@ def equals(self, other, failing_expression=False):
         # then we should have been able to compute that and so now
         # we can just consider the cases where the approximation appears
         # to be zero -- we try to prove it via minimal_polynomial.
+        #
+        # removed
+        # ns = nsimplify(diff)
+        # if diff.is_number and (not ns or ns == diff):
+        #
+        # The thought was that if it nsimplifies to 0 that's a sure sign
+        # to try the following to prove it; or if it changed but wasn't
+        # zero that might be a sign that it's not going to be easy to
+        # prove. But tests seem to be working without that logic.
+        #
         if diff.is_number:
-            approx = diff.nsimplify()
-            if not approx:
-                # try to prove via self-consistency
-                surds = [s for s in diff.atoms(Pow) if s.args[0].is_Integer]
-                # it seems to work better to try big ones first
-                surds.sort(key=lambda x: -x.args[0])
-                for s in surds:
-                    try:
-                        # simplify is False here -- this expression has already
-                        # been identified as being hard to identify as zero;
-                        # we will handle the checking ourselves using nsimplify
-                        # to see if we are in the right ballpark or not and if so
-                        # *then* the simplification will be attempted.
-                        if s.is_Symbol:
-                            sol = list(solveset(diff, s))
-                        else:
-                            sol = [s]
-                        if sol:
-                            if s in sol:
-                                return True
-                            if s.is_real:
-                                if any(nsimplify(si, [s]) == s and simplify(si) == s
-                                        for si in sol):
-                                    return True
-                    except NotImplementedError:
-                        pass
-
-                # try to prove with minimal_polynomial but know when
-                # *not* to use this or else it can take a long time. e.g. issue 8354
-                if True:  # change True to condition that assures non-hang
-                    try:
-                        mp = minimal_polynomial(diff)
-                        if mp.is_Symbol:
+            # try to prove via self-consistency
+            surds = [s for s in diff.atoms(Pow) if s.args[0].is_Integer]
+            # it seems to work better to try big ones first
+            surds.sort(key=lambda x: -x.args[0])
+            for s in surds:
+                try:
+                    # simplify is False here -- this expression has already
+                    # been identified as being hard to identify as zero;
+                    # we will handle the checking ourselves using nsimplify
+                    # to see if we are in the right ballpark or not and if so
+                    # *then* the simplification will be attempted.
+                    sol = solve(diff, s, simplify=False)
+                    if sol:
+                        if s in sol:
+                            # the self-consistent result is present
                             return True
-                        return False
-                    except (NotAlgebraic, NotImplementedError):
-                        pass
+                        if all(si.is_Integer for si in sol):
+                            # perfect powers are removed at instantiation
+                            # so surd s cannot be an integer
+                            return False
+                        if all(i.is_algebraic is False for i in sol):
+                            # a surd is algebraic
+                            return False
+                        if any(si in surds for si in sol):
+                            # it wasn't equal to s but it is in surds
+                            # and different surds are not equal
+                            return False
+                        if any(nsimplify(s - si) == 0 and
+                                simplify(s - si) == 0 for si in sol):
+                            return True
+                        if s.is_real:
+                            if any(nsimplify(si, [s]) == s and simplify(si) == s
+                                    for si in sol):
+                                return True
+                except NotImplementedError:
+                    pass
+
+            # try to prove with minimal_polynomial but know when
+            # *not* to use this or else it can take a long time. e.g. issue 8354
+            if True:  # change True to condition that assures non-hang
+                try:
+                    mp = minimal_polynomial(diff)
+                    if mp.is_Symbol:
+                        return True
+                    return False
+                except (NotAlgebraic, NotImplementedError):
+                    pass
 
         # diff has not simplified to zero; constant is either None, True
-        # or the number with significance (prec != 1) that was randomly
+        # or the number with significance (is_comparable) that was randomly
         # calculated twice as the same value.
         if constant not in (True, None) and constant != 0:
             return False
@@ -794,12 +819,12 @@ def _eval_is_positive(self):
             if n2 == S.NaN:
                 return None
 
-            n, i = self.evalf(2).as_real_imag()
-            if not i.is_Number or not n.is_Number:
+            r, i = self.evalf(2).as_real_imag()
+            if not i.is_Number or not r.is_Number:
                 return False
-            if n._prec != 1 and i._prec != 1:
-                return bool(not i and n > 0)
-            elif n._prec == 1 and (not i or i._prec == 1) and \
+            if r._prec != 1 and i._prec != 1:
+                return bool(not i and r > 0)
+            elif r._prec == 1 and (not i or i._prec == 1) and \
                     self.is_algebraic and not self.has(Function):
                 try:
                     if minimal_polynomial(self).is_Symbol:
@@ -829,12 +854,12 @@ def _eval_is_negative(self):
             if n2 == S.NaN:
                 return None
 
-            n, i = self.evalf(2).as_real_imag()
-            if not i.is_Number or not n.is_Number:
+            r, i = self.evalf(2).as_real_imag()
+            if not i.is_Number or not r.is_Number:
                 return False
-            if n._prec != 1 and i._prec != 1:
-                return bool(not i and n < 0)
-            elif n._prec == 1 and (not i or i._prec == 1) and \
+            if r._prec != 1 and i._prec != 1:
+                return bool(not i and r < 0)
+            elif r._prec == 1 and (not i or i._prec == 1) and \
                     self.is_algebraic and not self.has(Function):
                 try:
                     if minimal_polynomial(self).is_Symbol:
@@ -3407,7 +3432,7 @@ def round(self, n=None):
                 i *= -1
             return i*m
 
-        digits_to_decimal = _mag(x)
+        digits_to_decimal = _mag(x)  # _mag(12) = 2, _mag(.012) = -1
         allow = digits_needed = digits_to_decimal + p
         precs = [f._prec for f in x.atoms(Float)]
         dps = prec_to_dps(max(precs)) if precs else None
@@ -3491,7 +3516,7 @@ def round(self, n=None):
             if n is None:  # the single-arg case
                 return rv
             # use str or else it won't be a float
-            return Float(str(rv), digits_needed)
+            return Float(str(rv), dps)  # keep same precision
         else:
             if not allow and rv > self:
                 allow += 1
diff --git a/sympy/core/numbers.py b/sympy/core/numbers.py
index f7bef1ed8b..c2bd28d796 100644
--- a/sympy/core/numbers.py
+++ b/sympy/core/numbers.py
@@ -10,6 +10,7 @@
 from .sympify import converter, sympify, _sympify, SympifyError, _convert_numpy_types
 from .singleton import S, Singleton
 from .expr import Expr, AtomicExpr
+from .evalf import pure_complex
 from .decorators import _sympifyit
 from .cache import cacheit, clear_cache
 from .logic import fuzzy_not
@@ -20,13 +21,14 @@
 
 import mpmath
 import mpmath.libmp as mlib
+from mpmath.libmp import bitcount
 from mpmath.libmp.backend import MPZ
 from mpmath.libmp import mpf_pow, mpf_pi, mpf_e, phi_fixed
 from mpmath.ctx_mp import mpnumeric
 from mpmath.libmp.libmpf import (
     finf as _mpf_inf, fninf as _mpf_ninf,
-    fnan as _mpf_nan, fzero as _mpf_zero, _normalize as mpf_normalize,
-    prec_to_dps)
+    fnan as _mpf_nan, fzero, _normalize as mpf_normalize,
+    prec_to_dps, fone, fnone)
 from sympy.utilities.misc import debug, filldedent
 from .evaluate import global_evaluate
 
@@ -38,21 +40,69 @@
 
 
 def comp(z1, z2, tol=None):
-    """Return a bool indicating whether the error between z1 and z2 is <= tol.
-
-    If ``tol`` is None then True will be returned if there is a significant
-    difference between the numbers: ``abs(z1 - z2)*10**p <= 1/2`` where ``p``
-    is the lower of the precisions of the values. A comparison of strings will
-    be made if ``z1`` is a Number and a) ``z2`` is a string or b) ``tol`` is ''
-    and ``z2`` is a Number.
-
-    When ``tol`` is a nonzero value, if z2 is non-zero and ``|z1| > 1``
-    the error is normalized by ``|z1|``, so if you want to see if the
-    absolute error between ``z1`` and ``z2`` is <= ``tol`` then call this
-    as ``comp(z1 - z2, 0, tol)``.
+    """Return a bool indicating whether the error between z1 and z2
+    is <= tol.
+
+    Examples
+    ========
+
+    If ``tol`` is None then True will be returned if
+    ``abs(z1 - z2)*10**p <= 5`` where ``p`` is minimum value of the
+    decimal precision of each value.
+
+    >>> from sympy.core.numbers import comp, pi
+    >>> pi4 = pi.n(4); pi4
+    3.142
+    >>> comp(_, 3.142)
+    True
+    >>> comp(pi4, 3.141)
+    False
+    >>> comp(pi4, 3.143)
+    False
+
+    A comparison of strings will be made
+    if ``z1`` is a Number and ``z2`` is a string or ``tol`` is ''.
+
+    >>> comp(pi4, 3.1415)
+    True
+    >>> comp(pi4, 3.1415, '')
+    False
+
+    When ``tol`` is provided and ``z2`` is non-zero and
+    ``|z1| > 1`` the error is normalized by ``|z1|``:
+
+    >>> abs(pi4 - 3.14)/pi4
+    0.000509791731426756
+    >>> comp(pi4, 3.14, .001)  # difference less than 0.1%
+    True
+    >>> comp(pi4, 3.14, .0005)  # difference less than 0.1%
+    False
+
+    When ``|z1| <= 1`` the absolute error is used:
+
+    >>> 1/pi4
+    0.3183
+    >>> abs(1/pi4 - 0.3183)/(1/pi4)
+    3.07371499106316e-5
+    >>> abs(1/pi4 - 0.3183)
+    9.78393554684764e-6
+    >>> comp(1/pi4, 0.3183, 1e-5)
+    True
+
+    To see if the absolute error between ``z1`` and ``z2`` is less
+    than or equal to ``tol``, call this as ``comp(z1 - z2, 0, tol)``
+    or ``comp(z1 - z2, tol=tol)``:
+
+    >>> abs(pi4 - 3.14)
+    0.00160156249999988
+    >>> comp(pi4 - 3.14, 0, .002)
+    True
+    >>> comp(pi4 - 3.14, 0, .001)
+    False
     """
     if type(z2) is str:
-        if not isinstance(z1, Number):
+        z = sympify(z2)
+        if not pure_complex(z1, or_real=True):
             raise ValueError('when z2 is a str z1 must be a Number')
         return str(z1) == z2
     if not z1:
@@ -60,15 +110,37 @@ def comp(z1, z2, tol=None):
     if not z1:
         return True
     if not tol:
+        a, b = z1, z2
+        if tol == '':
+            return str(a) == str(b)
         if tol is None:
-            if type(z2) is str and getattr(z1, 'is_Number', False):
-                return str(z1) == z2
-            a, b = Float(z1), Float(z2)
-            return int(abs(a - b)*10**prec_to_dps(
-                min(a._prec, b._prec)))*2 <= 1
-        elif all(getattr(i, 'is_Number', False) for i in (z1, z2)):
-            return z1._prec == z2._prec and str(z1) == str(z2)
-        raise ValueError('exact comparison requires two Numbers')
+            a, b = sympify(a), sympify(b)
+            if not all(i.is_number for i in (a, b)):
+                raise ValueError('expecting 2 numbers')
+            fa = a.atoms(Float)
+            fb = b.atoms(Float)
+            if not fa and not fb:
+                # no floats -- compare exactly
+                return a == b
+            # get a to be pure_complex
+            for do in range(2):
+                ca = pure_complex(a, or_real=True)
+                if not ca:
+                    if fa:
+                        a = a.n(prec_to_dps(min([i._prec for i in fa])))
+                        ca = pure_complex(a, or_real=True)
+                        break
+                    else:
+                        fa, fb = fb, fa
+                        a, b = b, a
+            cb = pure_complex(b)
+            if not cb and fb:
+                b = b.n(prec_to_dps(min([i._prec for i in fb])))
+                cb = pure_complex(b, or_real=True)
+            if ca and cb and (ca[1] or cb[1]):
+                return all(comp(i, j) for i, j in zip(ca, cb))
+            tol = 10**prec_to_dps(min(a._prec, getattr(b, '_prec', a._prec)))
+            return int(abs(a - b)*tol) <= 5
     diff = abs(z1 - z2)
     az1 = abs(z1)
     if z2 and az1 > 1:
@@ -95,7 +167,7 @@ def mpf_norm(mpf, prec):
         # it assumes that if man is zero the result is 0
         # (see issue 6639)
         if not bc:
-            return _mpf_zero
+            return fzero
         else:
             # don't change anything; this should already
             # be a well formed mpf tuple
@@ -529,6 +601,15 @@ def __new__(cls, *obj):
         if isinstance(obj, (float, mpmath.mpf, decimal.Decimal)):
             return Float(obj)
         if isinstance(obj, string_types):
+            _obj = obj.lower()  # float('INF') == float('inf')
+            if _obj == 'nan':
+                return S.NaN
+            elif _obj == 'inf':
+                return S.Infinity
+            elif _obj == '+inf':
+                return S.Infinity
+            elif _obj == '-inf':
+                return S.NegativeInfinity
             val = sympify(obj)
             if isinstance(val, Number):
                 return val
@@ -927,6 +1008,14 @@ class Float(Number):
     precision. The mpf tuple and the precision are two separate quantities
     that Float tracks.
 
+    In SymPy, a Float is a number that can be computed with arbitrary
+    precision. Although floating point 'inf' and 'nan' are not such
+    numbers, Float can create these numbers:
+
+    >>> Float('-inf')
+    -oo
+    >>> _.is_Float
+    False
     """
     __slots__ = ['_mpf_', '_prec']
 
@@ -956,21 +1045,26 @@ def __new__(cls, num, dps=None, prec=None, precision=None):
                              'Supply only one. ')
 
         if isinstance(num, string_types):
-            # Float already accepts spaces as digit separators; in Py 3.6
+            # Float accepts spaces as digit separators
+            num = num.replace(' ', '').lower()
+            # in Py 3.6
             # underscores are allowed. In anticipation of that, we ignore
             # legally placed underscores
-            num = num.replace(' ', '')
             if '_' in num:
-                if num.startswith('_') or num.endswith('_') or any(
-                        i in num for i in ('__', '_.', '._')):
+                parts = num.split('_')
+                if not (all(parts) and
+                        all(parts[i][-1].isdigit()
+                            for i in range(0, len(parts), 2)) and
+                        all(parts[i][0].isdigit()
+                            for i in range(1, len(parts), 2))):
                     # copy Py 3.6 error
                     raise ValueError("could not convert string to float: '%s'" % num)
-                num = num.replace('_', '')
+                num = ''.join(parts)
             if num.startswith('.') and len(num) > 1:
                 num = '0' + num
             elif num.startswith('-.') and len(num) > 2:
                 num = '-0.' + num[2:]
-            elif num == 'inf' or num == '+inf':
+            elif num in ('inf', '+inf'):
                 return S.Infinity
             elif num == '-inf':
                 return S.NegativeInfinity
@@ -980,12 +1074,16 @@ def __new__(cls, num, dps=None, prec=None, precision=None):
             return S.Infinity
         elif isinstance(num, float) and num == float('-inf'):
             return S.NegativeInfinity
+        elif isinstance(num, float) and num == float('nan'):
+            return S.NaN
         elif isinstance(num, (SYMPY_INTS, Integer)):
-            num = str(num)  # faster than mlib.from_int
+            num = str(num)
         elif num is S.Infinity:
             return num
         elif num is S.NegativeInfinity:
             return num
+        elif num is S.NaN:
+            return num
         elif type(num).__module__ == 'numpy': # support for numpy datatypes
             num = _convert_numpy_types(num)
         elif isinstance(num, mpmath.mpf):
@@ -1052,8 +1150,7 @@ def __new__(cls, num, dps=None, prec=None, precision=None):
             elif num.is_infinite():
                 if num > 0:
                     return S.Infinity
-                else:
-                    return S.NegativeInfinity
+                return S.NegativeInfinity
             else:
                 raise ValueError("unexpected decimal value %s" % str(num))
         elif isinstance(num, tuple) and len(num) in (3, 4):
@@ -1073,33 +1170,30 @@ def __new__(cls, num, dps=None, prec=None, precision=None):
                     # handle normalization hack
                     return Float._new(num, precision)
                 else:
-                    return (S.NegativeOne**num[0]*num[1]*S(2)**num[2]).evalf(precision)
+                    if not all((
+                            num[0] in (0, 1),
+                            num[1] >= 0,
+                            all(type(i) in (long, int) for i in num)
+                            )):
+                        raise ValueError('malformed mpf: %s' % (num,))
+                    # don't compute number or else it may
+                    # over/underflow
+                    return Float._new(
+                        (num[0], num[1], num[2], bitcount(num[1])),
+                        precision)
         else:
             try:
                 _mpf_ = num._as_mpf_val(precision)
             except (NotImplementedError, AttributeError):
                 _mpf_ = mpmath.mpf(num, prec=precision)._mpf_
 
-        # special cases
-        if _mpf_ == _mpf_zero:
-            pass  # we want a Float
-        elif _mpf_ == _mpf_nan:
-            return S.NaN
-        elif _mpf_ == _mpf_inf:
-            return S.Infinity
-        elif _mpf_ == _mpf_ninf:
-            return S.NegativeInfinity
-
-        obj = Expr.__new__(cls)
-        obj._mpf_ = _mpf_
-        obj._prec = precision
-        return obj
+        return cls._new(_mpf_, precision, zero=False)
 
     @classmethod
-    def _new(cls, _mpf_, _prec):
+    def _new(cls, _mpf_, _prec, zero=True):
         # special cases
-        if _mpf_ == _mpf_zero:
-            return S.Zero  # XXX this is different from Float which gives 0.0
+        if zero and _mpf_ == fzero:
+            return S.Zero  # Float(0) -> 0.0; Float._new((0,0,0,0)) -> 0
         elif _mpf_ == _mpf_nan:
             return S.NaN
         elif _mpf_ == _mpf_inf:
@@ -1109,7 +1203,6 @@ def _new(cls, _mpf_, _prec):
 
         obj = Expr.__new__(cls)
         obj._mpf_ = mpf_norm(_mpf_, _prec)
-        # XXX: Should this be obj._prec = obj._mpf_[3]?
         obj._prec = _prec
         return obj
 
@@ -1137,7 +1230,6 @@ def __floor__(self):
     def __ceil__(self):
         return self.ceiling()
 
-
     @property
     def num(self):
         return mpmath.mpf(self._mpf_)
@@ -1162,7 +1254,7 @@ def _eval_is_infinite(self):
         return False
 
     def _eval_is_integer(self):
-        return self._mpf_ == _mpf_zero
+        return self._mpf_ == fzero
 
     def _eval_is_negative(self):
         if self._mpf_ == _mpf_ninf:
@@ -1179,10 +1271,10 @@ def _eval_is_positive(self):
         return self.num > 0
 
     def _eval_is_zero(self):
-        return self._mpf_ == _mpf_zero
+        return self._mpf_ == fzero
 
     def __nonzero__(self):
-        return self._mpf_ != _mpf_zero
+        return self._mpf_ != fzero
 
     __bool__ = __nonzero__
 
@@ -1271,7 +1363,7 @@ def _eval_power(self, expt):
                 return Float._new(y, prec)
             except mlib.ComplexResult:
                 re, im = mlib.mpc_pow(
-                    (mpfself, _mpf_zero), (expt, _mpf_zero), prec, rnd)
+                    (mpfself, fzero), (expt, fzero), prec, rnd)
                 return Float._new(re, prec) + \
                     Float._new(im, prec)*S.ImaginaryUnit
 
@@ -1279,31 +1371,29 @@ def __abs__(self):
         return Float._new(mlib.mpf_abs(self._mpf_), self._prec)
 
     def __int__(self):
-        if self._mpf_ == _mpf_zero:
+        if self._mpf_ == fzero:
             return 0
         return int(mlib.to_int(self._mpf_))  # uses round_fast = round_down
 
     __long__ = __int__
 
     def __eq__(self, other):
-        if isinstance(other, float):
-            # coerce to Float at same precision
-            o = Float(other)
-            try:
-                ompf = o._as_mpf_val(self._prec)
-            except ValueError:
-                return False
-            return bool(mlib.mpf_eq(self._mpf_, ompf))
         try:
             other = _sympify(other)
         except SympifyError:
             return NotImplemented
+        if not self:
+            return not other
         if other.is_NumberSymbol:
             if other.is_irrational:
                 return False
             return other.__eq__(self)
         if other.is_Float:
-            return bool(mlib.mpf_eq(self._mpf_, other._mpf_))
+            # comparison is exact
+            # so Float(.1, 3) != Float(.1, 33)
+            return self._mpf_ == other._mpf_
+        if other.is_Rational:
+            return other.__eq__(self)
         if other.is_Number:
             # numbers should compare at the same precision;
             # all _as_mpf_val routines should be sure to abide
@@ -1317,73 +1407,68 @@ def __eq__(self, other):
     def __ne__(self, other):
         return not self == other
 
-    def __gt__(self, other):
+    def _Frel(self, other, op):
+        from sympy.core.evalf import evalf
+        from sympy.core.numbers import prec_to_dps
         try:
             other = _sympify(other)
         except SympifyError:
             raise TypeError("Invalid comparison %s > %s" % (self, other))
-        if other.is_NumberSymbol:
-            return other.__lt__(self)
-        if other.is_Rational and not other.is_Integer:
-            self *= other.q
-            other = _sympify(other.p)
-        elif other.is_comparable:
-            other = other.evalf()
-        if other.is_Number and other is not S.NaN:
+        if other.is_Rational:
+            # test self*other.q <?> other.p without losing precision
+            '''
+            >>> f = Float(.1,2)
+            >>> i = 1234567890
+            >>> (f*i)._mpf_
+            (0, 471, 18, 9)
+            >>> mlib.mpf_mul(f._mpf_, mlib.from_int(i))
+            (0, 505555550955, -12, 39)
+            '''
+            smpf = mlib.mpf_mul(self._mpf_, mlib.from_int(other.q))
+            ompf = mlib.from_int(other.p)
+            return _sympify(bool(op(smpf, ompf)))
+        elif other.is_Float:
             return _sympify(bool(
-                mlib.mpf_gt(self._mpf_, other._as_mpf_val(self._prec))))
-        return Expr.__gt__(self, other)
+                        op(self._mpf_, other._mpf_)))
+        elif other.is_comparable and other not in (
+                S.Infinity, S.NegativeInfinity):
+            other = other.evalf(prec_to_dps(self._prec))
+            if other._prec > 1:
+                if other.is_Number:
+                    return _sympify(bool(
+                        op(self._mpf_, other._as_mpf_val(self._prec))))
+
+    def __gt__(self, other):
+        if isinstance(other, NumberSymbol):
+            return other.__lt__(self)
+        rv = self._Frel(other, mlib.mpf_gt)
+        if rv is None:
+            return Expr.__gt__(self, other)
+        return rv
 
     def __ge__(self, other):
-        try:
-            other = _sympify(other)
-        except SympifyError:
-            raise TypeError("Invalid comparison %s >= %s" % (self, other))
-        if other.is_NumberSymbol:
+        if isinstance(other, NumberSymbol):
             return other.__le__(self)
-        if other.is_Rational and not other.is_Integer:
-            self *= other.q
-            other = _sympify(other.p)
-        elif other.is_comparable:
-            other = other.evalf()
-        if other.is_Number and other is not S.NaN:
-            return _sympify(bool(
-                mlib.mpf_ge(self._mpf_, other._as_mpf_val(self._prec))))
-        return Expr.__ge__(self, other)
+        rv = self._Frel(other, mlib.mpf_ge)
+        if rv is None:
+            return Expr.__ge__(self, other)
+        return rv
 
     def __lt__(self, other):
-        try:
-            other = _sympify(other)
-        except SympifyError:
-            raise TypeError("Invalid comparison %s < %s" % (self, other))
-        if other.is_NumberSymbol:
+        if isinstance(other, NumberSymbol):
             return other.__gt__(self)
-        if other.is_Rational and not other.is_Integer:
-            self *= other.q
-            other = _sympify(other.p)
-        elif other.is_comparable:
-            other = other.evalf()
-        if other.is_Number and other is not S.NaN:
-            return _sympify(bool(
-                mlib.mpf_lt(self._mpf_, other._as_mpf_val(self._prec))))
-        return Expr.__lt__(self, other)
+        rv = self._Frel(other, mlib.mpf_lt)
+        if rv is None:
+            return Expr.__lt__(self, other)
+        return rv
 
     def __le__(self, other):
-        try:
-            other = _sympify(other)
-        except SympifyError:
-            raise TypeError("Invalid comparison %s <= %s" % (self, other))
-        if other.is_NumberSymbol:
+        if isinstance(other, NumberSymbol):
             return other.__ge__(self)
-        if other.is_Rational and not other.is_Integer:
-            self *= other.q
-            other = _sympify(other.p)
-        elif other.is_comparable:
-            other = other.evalf()
-        if other.is_Number and other is not S.NaN:
-            return _sympify(bool(
-                mlib.mpf_le(self._mpf_, other._as_mpf_val(self._prec))))
-        return Expr.__le__(self, other)
+        rv = self._Frel(other, mlib.mpf_le)
+        if rv is None:
+            return Expr.__le__(self, other)
+        return rv
 
     def __hash__(self):
         return super(Float, self).__hash__()
@@ -1770,97 +1855,106 @@ def __ceil__(self):
         return self.ceiling()
 
     def __eq__(self, other):
+        from sympy.core.power import integer_log
         try:
             other = _sympify(other)
         except SympifyError:
             return NotImplemented
+        if not isinstance(other, Number):
+            # S(0) == S.false is False
+            # S(0) == False is True
+            return False
+        if not self:
+            return not other
         if other.is_NumberSymbol:
             if other.is_irrational:
                 return False
             return other.__eq__(self)
-        if other.is_Number:
-            if other.is_Rational:
-                # a Rational is always in reduced form so will never be 2/4
-                # so we can just check equivalence of args
-                return self.p == other.p and self.q == other.q
-            if other.is_Float:
-                return mlib.mpf_eq(self._as_mpf_val(other._prec), other._mpf_)
+        if other.is_Rational:
+            # a Rational is always in reduced form so will never be 2/4
+            # so we can just check equivalence of args
+            return self.p == other.p and self.q == other.q
+        if other.is_Float:
+            # all Floats have a denominator that is a power of 2
+            # so if self doesn't, it can't be equal to other
+            if self.q & (self.q - 1):
+                return False
+            s, m, t = other._mpf_[:3]
+            if s:
+                m = -m
+            if not t:
+                # other is an odd integer
+                if not self.is_Integer or self.is_even:
+                    return False
+                return m == self.p
+            if t > 0:
+                # other is an even integer
+                if not self.is_Integer:
+                    return False
+                # does m*2**t == self.p
+                return self.p and not self.p % m and \
+                    integer_log(self.p//m, 2) == (t, True)
+            # does non-integer s*m/2**-t = p/q?
+            if self.is_Integer:
+                return False
+            return m == self.p and integer_log(self.q, 2) == (-t, True)
         return False
 
     def __ne__(self, other):
         return not self == other
 
-    def __gt__(self, other):
+    def _Rrel(self, other, attr):
+        # if you want self < other, pass self, other, __gt__
         try:
             other = _sympify(other)
         except SympifyError:
             raise TypeError("Invalid comparison %s > %s" % (self, other))
-        if other.is_NumberSymbol:
-            return other.__lt__(self)
-        expr = self
         if other.is_Number:
-            if other.is_Rational:
-                return _sympify(bool(self.p*other.q > self.q*other.p))
-            if other.is_Float:
-                return _sympify(bool(mlib.mpf_gt(
-                    self._as_mpf_val(other._prec), other._mpf_)))
-        elif other.is_number and other.is_real:
-            expr, other = Integer(self.p), self.q*other
-        return Expr.__gt__(expr, other)
+            op = None
+            s, o = self, other
+            if other.is_NumberSymbol:
+                op = getattr(o, attr)
+            elif other.is_Float:
+                op = getattr(o, attr)
+            elif other.is_Rational:
+                s, o = Integer(s.p*o.q), Integer(s.q*o.p)
+                op = getattr(o, attr)
+            if op:
+                return op(s)
+            if o.is_number and o.is_real:
+                return Integer(s.p), s.q*o
+
+    def __gt__(self, other):
+        rv = self._Rrel(other, '__lt__')
+        if rv is None:
+            rv = self, other
+        elif not type(rv) is tuple:
+            return rv
+        return Expr.__gt__(*rv)
 
     def __ge__(self, other):
-        try:
-            other = _sympify(other)
-        except SympifyError:
-            raise TypeError("Invalid comparison %s >= %s" % (self, other))
-        if other.is_NumberSymbol:
-            return other.__le__(self)
-        expr = self
-        if other.is_Number:
-            if other.is_Rational:
-                 return _sympify(bool(self.p*other.q >= self.q*other.p))
-            if other.is_Float:
-                return _sympify(bool(mlib.mpf_ge(
-                    self._as_mpf_val(other._prec), other._mpf_)))
-        elif other.is_number and other.is_real:
-            expr, other = Integer(self.p), self.q*other
-        return Expr.__ge__(expr, other)
+        rv = self._Rrel(other, '__le__')
+        if rv is None:
+            rv = self, other
+        elif not type(rv) is tuple:
+            return rv
+        return Expr.__ge__(*rv)
 
     def __lt__(self, other):
-        try:
-            other = _sympify(other)
-        except SympifyError:
-            raise TypeError("Invalid comparison %s < %s" % (self, other))
-        if other.is_NumberSymbol:
-            return other.__gt__(self)
-        expr = self
-        if other.is_Number:
-            if other.is_Rational:
-                return _sympify(bool(self.p*other.q < self.q*other.p))
-            if other.is_Float:
-                return _sympify(bool(mlib.mpf_lt(
-                    self._as_mpf_val(other._prec), other._mpf_)))
-        elif other.is_number and other.is_real:
-            expr, other = Integer(self.p), self.q*other
-        return Expr.__lt__(expr, other)
+        rv = self._Rrel(other, '__gt__')
+        if rv is None:
+            rv = self, other
+        elif not type(rv) is tuple:
+            return rv
+        return Expr.__lt__(*rv)
 
     def __le__(self, other):
-        try:
-            other = _sympify(other)
-        except SympifyError:
-            raise TypeError("Invalid comparison %s <= %s" % (self, other))
-        expr = self
-        if other.is_NumberSymbol:
-            return other.__ge__(self)
-        elif other.is_Number:
-            if other.is_Rational:
-                return _sympify(bool(self.p*other.q <= self.q*other.p))
-            if other.is_Float:
-                return _sympify(bool(mlib.mpf_le(
-                    self._as_mpf_val(other._prec), other._mpf_)))
-        elif other.is_number and other.is_real:
-            expr, other = Integer(self.p), self.q*other
-        return Expr.__le__(expr, other)
+        rv = self._Rrel(other, '__ge__')
+        if rv is None:
+            rv = self, other
+        elif not type(rv) is tuple:
+            return rv
+        return Expr.__le__(*rv)
 
     def __hash__(self):
         return super(Rational, self).__hash__()
@@ -2211,7 +2305,7 @@ def _eval_power(self, expt):
         the argument which is not done here for sake of speed.
 
         """
-        from sympy import perfect_power
+        from sympy.ntheory.factor_ import perfect_power
 
         if expt is S.Infinity:
             if self.p > S.One:
diff --git a/sympy/core/power.py b/sympy/core/power.py
index 50e7221018..fca6f3c1ad 100644
--- a/sympy/core/power.py
+++ b/sympy/core/power.py
@@ -256,6 +256,8 @@ def __new__(cls, b, e, evaluate=None):
                 return S.One
             elif e is S.One:
                 return b
+            elif e == -1 and not b:
+                return S.ComplexInfinity
             # Only perform autosimplification if exponent or base is a Symbol or number
             elif (b.is_Symbol or b.is_number) and (e.is_Symbol or e.is_number) and\
                 e.is_integer and _coeff_isneg(b):
@@ -677,7 +679,7 @@ def _check(ct1, ct2, old):
                     # Allow fractional powers for commutative objects
                     pow = coeff1/coeff2
                     try:
-                        pow = as_int(pow, strict=False)
+                        as_int(pow, strict=False)
                         combines = True
                     except ValueError:
                         combines = isinstance(Pow._eval_power(
diff --git a/sympy/core/relational.py b/sympy/core/relational.py
index 28bd38209d..9f12169538 100644
--- a/sympy/core/relational.py
+++ b/sympy/core/relational.py
@@ -18,6 +18,7 @@
 )
 
 
+
 # Note, see issue 4986.  Ideally, we wouldn't want to subclass both Boolean
 # and Expr.
 
diff --git a/sympy/geometry/ellipse.py b/sympy/geometry/ellipse.py
index 4c65c1872e..6990646034 100644
--- a/sympy/geometry/ellipse.py
+++ b/sympy/geometry/ellipse.py
@@ -738,7 +738,13 @@ def is_tangent(self, o):
             else:
                 return False
         elif isinstance(o, Line2D):
-            return len(self.intersection(o)) == 1
+            hit = self.intersection(o)
+            if not hit:
+                return False
+            if len(hit) == 1:
+                return True
+            # might return None if it can't decide
+            return hit[0].equals(hit[1])
         elif isinstance(o, Ray2D):
             intersect = self.intersection(o)
             if len(intersect) == 1:
diff --git a/sympy/geometry/point.py b/sympy/geometry/point.py
index 489fd5c477..be5e4d568d 100644
--- a/sympy/geometry/point.py
+++ b/sympy/geometry/point.py
@@ -324,7 +324,9 @@ def affine_rank(*args):
         points = [i - origin for i in points[1:]]
 
         m = Matrix([i.args for i in points])
-        return m.rank()
+        # XXX fragile -- what is a better way?
+        return m.rank(iszerofunc = lambda x:
+            abs(x.n(2)) < 1e-12 if x.is_number else x.is_zero)
 
     @property
     def ambient_dimension(self):
diff --git a/sympy/ntheory/factor_.py b/sympy/ntheory/factor_.py
index ff4b14b57f..1c187d79fd 100644
--- a/sympy/ntheory/factor_.py
+++ b/sympy/ntheory/factor_.py
@@ -285,20 +285,21 @@ def multiplicity(p, n):
 def perfect_power(n, candidates=None, big=True, factor=True):
     """
     Return ``(b, e)`` such that ``n`` == ``b**e`` if ``n`` is a
-    perfect power; otherwise return ``False``.
+    perfect power with ``e > 1``, else ``False``. A ValueError is
+    raised if ``n`` is not an integer or is not positive.
 
     By default, the base is recursively decomposed and the exponents
     collected so the largest possible ``e`` is sought. If ``big=False``
     then the smallest possible ``e`` (thus prime) will be chosen.
 
-    If ``candidates`` for exponents are given, they are assumed to be sorted
-    and the first one that is larger than the computed maximum will signal
-    failure for the routine.
+    If ``candidates`` for exponents are given, they are assumed to be
+    sorted and the first one that is larger than the computed maximum
+    will signal failure for the routine.
 
-    If ``factor=True`` then simultaneous factorization of n is attempted
-    since finding a factor indicates the only possible root for n. This
-    is True by default since only a few small factors will be tested in
-    the course of searching for the perfect power.
+    If ``factor=True`` then simultaneous factorization of n is
+    attempted since finding a factor indicates the only possible root
+    for n. This is True by default since only a few small factors will
+    be tested in the course of searching for the perfect power.
 
     Examples
     ========
@@ -306,11 +307,22 @@ def perfect_power(n, candidates=None, big=True, factor=True):
     >>> from sympy import perfect_power
     >>> perfect_power(16)
     (2, 4)
-    >>> perfect_power(16, big = False)
+    >>> perfect_power(16, big=False)
     (4, 2)
+
+    Notes
+    =====
+
+    To know whether an integer is a perfect power of 2 use
+
+    >>> is2pow = lambda n: bool(n and not n & (n - 1))
+    >>> [(i, is2pow(i)) for i in range(5)]
+    [(0, False), (1, True), (2, True), (3, False), (4, True)]
     """
-    n = int(n)
+    n = as_int(n)
     if n < 3:
+        if n < 1:
+            raise ValueError('expecting positive n')
         return False
     logn = math.log(n, 2)
     max_possible = int(logn) + 2  # only check values less than this
diff --git a/sympy/physics/hydrogen.py b/sympy/physics/hydrogen.py
index 65f19704e1..8ec8e6c2da 100644
--- a/sympy/physics/hydrogen.py
+++ b/sympy/physics/hydrogen.py
@@ -70,7 +70,7 @@ def R_nl(n, l, r, Z=1):
 
     """
     # sympify arguments
-    n, l, r, Z = S(n), S(l), S(r), S(Z)
+    n, l, r, Z = map(S, [n, l, r, Z])
     # radial quantum number
     n_r = n - l - 1
     # rescaled "r"
@@ -83,6 +83,7 @@ def R_nl(n, l, r, Z=1):
     # C =  S(2)/n**2 * sqrt(1/a**3 * factorial(n_r) / (factorial(n+l)))
     return C * r0**l * assoc_laguerre(n_r, 2*l + 1, r0).expand() * exp(-r0/2)
 
+
 def Psi_nlm(n, l, m, r, phi, theta, Z=1):
     """
     Returns the Hydrogen wave function psi_{nlm}. It's the product of
@@ -129,17 +130,16 @@ def Psi_nlm(n, l, m, r, phi, theta, Z=1):
     """
 
     # sympify arguments
-    n, l, m, r, phi, theta, Z = S(n), S(l), S(m), S(r), S(phi), S(theta), S(Z)
+    n, l, m, r, phi, theta, Z = map(S, [n, l, m, r, phi, theta, Z])
     # check if values for n,l,m make physically sense
-    if n.is_integer and n<1:
+    if n.is_integer and n < 1:
         raise ValueError("'n' must be positive integer")
     if l.is_integer and not (n > l):
         raise ValueError("'n' must be greater than 'l'")
-    if m.is_integer and not (abs(m)<=l):
+    if m.is_integer and not (abs(m) <= l):
         raise ValueError("|'m'| must be less or equal 'l'")
     # return the hydrogen wave function
-    return R_nl(n, l, r, Z)*Ynm(l,m,theta,phi).expand(func=True)
-
+    return R_nl(n, l, r, Z)*Ynm(l, m, theta, phi).expand(func=True)
 
 
 def E_nl(n, Z=1):
@@ -217,6 +217,7 @@ def E_nl_dirac(n, l, spin_up=True, Z=1, c=Float("137.035999037")):
     -0.0555558020932949
 
     """
+    n, l, Z, c = map(S, [n, l, Z, c])
     if not (l >= 0):
         raise ValueError("'l' must be positive or zero")
     if not (n > l):
@@ -228,6 +229,5 @@ def E_nl_dirac(n, l, spin_up=True, Z=1, c=Float("137.035999037")):
         skappa = -l - 1
     else:
         skappa = -l
-    c = S(c)
     beta = sqrt(skappa**2 - Z**2/c**2)
     return c**2/sqrt(1 + Z**2/(n + skappa + beta)**2/c**2) - c**2
diff --git a/sympy/solvers/ode.py b/sympy/solvers/ode.py
index 196b9d6a61..a49d2b68e4 100644
--- a/sympy/solvers/ode.py
+++ b/sympy/solvers/ode.py
@@ -4055,7 +4055,7 @@ def ode_nth_order_reducible(eq, func, order, match):
     >>> from sympy import Function, dsolve, Eq
     >>> from sympy.abc import x
     >>> f = Function('f')
-    >>> eq = Eq(x*f(x).diff(x)**2 + f(x).diff(x, 2))
+    >>> eq = Eq(x*f(x).diff(x)**2 + f(x).diff(x, 2), 0)
     >>> dsolve(eq, f(x), hint='nth_order_reducible')
     ... # doctest: +NORMALIZE_WHITESPACE
     Eq(f(x), C1 - sqrt(-1/C2)*log(-C2*sqrt(-1/C2) + x) + sqrt(-1/C2)*log(C2*sqrt(-1/C2) + x))


Test patch:
diff --git a/sympy/concrete/tests/test_sums_products.py b/sympy/concrete/tests/test_sums_products.py
index 576977163b..76dfc5deda 100644
--- a/sympy/concrete/tests/test_sums_products.py
+++ b/sympy/concrete/tests/test_sums_products.py
@@ -265,7 +265,7 @@ def test_geometric_sums():
     assert result.is_Float
 
     result = Sum(0.25**n, (n, 1, oo)).doit()
-    assert result == S(1)/3
+    assert result == 1/3.
     assert result.is_Float
 
     result = Sum(0.99999**n, (n, 1, oo)).doit()
diff --git a/sympy/core/tests/test_arit.py b/sympy/core/tests/test_arit.py
index a2b2b9826a..104a894cb1 100644
--- a/sympy/core/tests/test_arit.py
+++ b/sympy/core/tests/test_arit.py
@@ -271,7 +271,7 @@ def test_pow_im():
 
 
 def test_real_mul():
-    assert Float(0) * pi * x == Float(0)
+    assert Float(0) * pi * x == 0
     assert set((Float(1) * pi * x).args) == {Float(1), pi, x}
 
 
diff --git a/sympy/core/tests/test_evalf.py b/sympy/core/tests/test_evalf.py
index 4a837ed7d4..5bd637eceb 100644
--- a/sympy/core/tests/test_evalf.py
+++ b/sympy/core/tests/test_evalf.py
@@ -2,6 +2,7 @@
     factorial, fibonacci, floor, Function, GoldenRatio, I, Integral,
     integrate, log, Mul, N, oo, pi, Pow, product, Product,
     Rational, S, Sum, simplify, sin, sqrt, sstr, sympify, Symbol, Max, nfloat)
+from sympy.core.numbers import comp
 from sympy.core.evalf import (complex_accuracy, PrecisionExhausted,
     scaled_zero, get_integer_part, as_mpmath, evalf)
 from mpmath import inf, ninf
@@ -234,6 +235,7 @@ def test_evalf_bugs():
     #issue 13076
     assert NS(Mul(Max(0, y), x, evaluate=False).evalf()) == 'x*Max(0, y)'
 
+
 def test_evalf_integer_parts():
     a = floor(log(8)/log(2) - exp(-1000), evaluate=False)
     b = floor(log(8)/log(2), evaluate=False)
@@ -252,15 +254,16 @@ def test_evalf_integer_parts():
                .evalf(1000)) == fibonacci(1000)
 
     assert ceiling(x).evalf(subs={x: 3}) == 3
-    assert ceiling(x).evalf(subs={x: 3*I}) == 3*I
-    assert ceiling(x).evalf(subs={x: 2 + 3*I}) == 2 + 3*I
+    assert ceiling(x).evalf(subs={x: 3*I}) == 3.0*I
+    assert ceiling(x).evalf(subs={x: 2 + 3*I}) == 2.0 + 3.0*I
     assert ceiling(x).evalf(subs={x: 3.}) == 3
-    assert ceiling(x).evalf(subs={x: 3.*I}) == 3*I
-    assert ceiling(x).evalf(subs={x: 2. + 3*I}) == 2 + 3*I
+    assert ceiling(x).evalf(subs={x: 3.*I}) == 3.0*I
+    assert ceiling(x).evalf(subs={x: 2. + 3*I}) == 2.0 + 3.0*I
 
     assert float((floor(1.5, evaluate=False)+1/9).evalf()) == 1 + 1/9
     assert float((floor(0.5, evaluate=False)+20).evalf()) == 20
 
+
 def test_evalf_trig_zero_detection():
     a = sin(160*pi, evaluate=False)
     t = a.evalf(maxn=100)
@@ -299,7 +302,7 @@ def test_evalf_divergent_series():
 
 def test_evalf_product():
     assert Product(n, (n, 1, 10)).evalf() == 3628800.
-    assert Product(1 - S.Half**2/n**2, (n, 1, oo)).evalf(5)==0.63662
+    assert comp(Product(1 - S.Half**2/n**2, (n, 1, oo)).n(5), 0.63662)
     assert Product(n, (n, -1, 3)).evalf() == 0
 
 
diff --git a/sympy/core/tests/test_expr.py b/sympy/core/tests/test_expr.py
index 6272ae19ac..b51b421f17 100644
--- a/sympy/core/tests/test_expr.py
+++ b/sympy/core/tests/test_expr.py
@@ -1652,15 +1652,15 @@ def test_random():
 def test_round():
     from sympy.abc import x
 
-    assert Float('0.1249999').round(2) == 0.12
+    assert str(Float('0.1249999').round(2)) == '0.12'
     d20 = 12345678901234567890
     ans = S(d20).round(2)
     assert ans.is_Integer and ans == d20
     ans = S(d20).round(-2)
     assert ans.is_Integer and ans == 12345678901234567900
-    assert S('1/7').round(4) == 0.1429
-    assert S('.[12345]').round(4) == 0.1235
-    assert S('.1349').round(2) == 0.13
+    assert str(S('1/7').round(4)) == '0.1429'
+    assert str(S('.[12345]').round(4)) == '0.1235'
+    assert str(S('.1349').round(2)) == '0.13'
     n = S(12345)
     ans = n.round()
     assert ans.is_Integer
@@ -1675,16 +1675,13 @@ def test_round():
 
     r = Float(str(n)).round(-4)
     assert r == 10000
-    # in fact, it should equal many values since __eq__
-    # compares at equal precision
-    assert all(r == i for i in range(9984, 10049))
 
     assert n.round(-5) == 0
 
-    assert (pi + sqrt(2)).round(2) == 4.56
+    assert str((pi + sqrt(2)).round(2)) == '4.56'
     assert (10*(pi + sqrt(2))).round(-1) == 50
     raises(TypeError, lambda: round(x + 2, 2))
-    assert S(2.3).round(1) == 2.3
+    assert str(S(2.3).round(1)) == '2.3'
     # rounding in SymPy (as in Decimal) should be
     # exact for the given precision; we check here
     # that when a 5 follows the last digit that
@@ -1709,8 +1706,8 @@ def test_round():
     assert (pi + 2*E*I).round() == 3 + 5*I
     # don't let request for extra precision give more than
     # what is known (in this case, only 3 digits)
-    assert (Float(.03, 3) + 2*pi/100).round(5) == 0.0928
-    assert (Float(.03, 3) + 2*pi/100).round(4) == 0.0928
+    assert str((Float(.03, 3) + 2*pi/100).round(5)) == '0.0928'
+    assert str((Float(.03, 3) + 2*pi/100).round(4)) == '0.0928'
 
     assert S.Zero.round() == 0
 
@@ -1739,8 +1736,8 @@ def test_round():
     # then coerce the floats to the same precision) or re-create
     # the floats
     assert str((pi/10 + E*I).round(2)) == '0.31 + 2.72*I'
-    assert (pi/10 + E*I).round(2).as_real_imag() == (0.31, 2.72)
-    assert (pi/10 + E*I).round(2) == Float(0.31, 2) + I*Float(2.72, 3)
+    assert str((pi/10 + E*I).round(2).as_real_imag()) == '(0.31, 2.72)'
+    assert str((pi/10 + E*I).round(2)) == '0.31 + 2.72*I'
 
     # issue 6914
     assert (I**(I + 3)).round(3) == Float('-0.208', '')*I
diff --git a/sympy/core/tests/test_numbers.py b/sympy/core/tests/test_numbers.py
index 4487665b0b..b1a604949a 100644
--- a/sympy/core/tests/test_numbers.py
+++ b/sympy/core/tests/test_numbers.py
@@ -56,7 +56,7 @@ def test_mod():
 
     a = Float(2.6)
 
-    assert (a % .2) == 0
+    assert (a % .2) == 0.0
     assert (a % 2).round(15) == 0.6
     assert (a % 0.5).round(15) == 0.1
 
@@ -83,7 +83,7 @@ def test_mod():
 
     s = S.Zero
 
-    assert s % float(1) == S.Zero
+    assert s % float(1) == 0.0
 
     # No rounding required since these numbers can be represented
     # exactly.
@@ -132,12 +132,12 @@ def test_divmod():
     assert divmod(0.3, S("2")) == Tuple(S("0"), S("0.3"))
     assert divmod(S("3/2"), S("3.5")) == Tuple(S("0"), S("3/2"))
     assert divmod(S("3.5"), S("3/2")) == Tuple(S("2"), S("0.5"))
-    assert divmod(S("3/2"), S("1/3")) == Tuple(S("4"), Float("1/6"))
+    assert divmod(S("3/2"), S("1/3")) == Tuple(S("4"), S("1/6"))
     assert divmod(S("1/3"), S("3/2")) == Tuple(S("0"), S("1/3"))
     assert divmod(S("3/2"), S("0.1"))[0] == 14
     assert divmod(S("0.1"), S("3/2")) == Tuple(S("0"), S("0.1"))
     assert divmod(S("3/2"), 2) == Tuple(S("0"), S("3/2"))
-    assert divmod(2, S("3/2")) == Tuple(S("1"), S("0.5"))
+    assert divmod(2, S("3/2")) == Tuple(S("1"), S("1/2"))
     assert divmod(S("3/2"), 1.5) == Tuple(S("1"), S("0"))
     assert divmod(1.5, S("3/2")) == Tuple(S("1"), S("0"))
     assert divmod(S("3/2"), 0.3) == Tuple(S("5"), S("0"))
@@ -184,7 +184,6 @@ def test_divmod():
     OO = float('inf')
     ANS = [tuple(map(float, i)) for i in ans]
     assert [divmod(i, oo) for i in range(-2, 3)] == ans
-    assert [divmod(i, OO) for i in range(-2, 3)] ==  ANS
     ans = [(0, -2), (0, -1), (0, 0), (-1, -oo), (-1, -oo)]
     ANS = [tuple(map(float, i)) for i in ans]
     assert [divmod(i, -oo) for i in range(-2, 3)] == ans
@@ -365,6 +364,10 @@ def test_Number_new():
     raises(TypeError, lambda: Number(cos))
     a = Rational(3, 5)
     assert Number(a) is a  # Check idempotence on Numbers
+    u = ['inf', '-inf', 'nan', 'iNF', '+inf']
+    v = [oo, -oo, nan, oo, oo]
+    for i, a in zip(u, v):
+        assert Number(i) is a, (i, Number(i), a)
 
 
 def test_Number_cmp():
@@ -421,35 +424,40 @@ def eq(a, b):
         t = Float("1.0E-15")
         return (-t < a - b < t)
 
+    zeros = (0, S(0), 0., Float(0))
+    for i, j in permutations(zeros, 2):
+        assert i == j
+    for z in zeros:
+        assert z in zeros
+    assert S(0).is_zero
+
     a = Float(2) ** Float(3)
     assert eq(a.evalf(), Float(8))
     assert eq((pi ** -1).evalf(), Float("0.31830988618379067"))
     a = Float(2) ** Float(4)
     assert eq(a.evalf(), Float(16))
     assert (S(.3) == S(.5)) is False
-    x_str = Float((0, '13333333333333', -52, 53))
-    x2_str = Float((0, '26666666666666', -53, 53))
+    mpf = (0, 5404319552844595, -52, 53)
+    x_str =  Float((0, '13333333333333', -52, 53))
+    x2_str = Float((0, '26666666666666', -53, 54))
     x_hex = Float((0, long(0x13333333333333), -52, 53))
-    x_dec = Float((0, 5404319552844595, -52, 53))
+    x_dec = Float(mpf)
     assert x_str == x_hex == x_dec == Float(1.2)
-    # This looses a binary digit of precision, so it isn't equal to the above,
-    # but check that it normalizes correctly
-    x2_hex = Float((0, long(0x13333333333333)*2, -53, 53))
-    assert x2_hex._mpf_ == (0, 5404319552844595, -52, 52)
-    # XXX: Should this test also hold?
-    # assert x2_hex._prec == 52
-
-    # x2_str and 1.2 are superficially the same
-    assert str(x2_str) == str(Float(1.2))
-    # but are different at the mpf level
-    assert Float(1.2)._mpf_ == (0, long(5404319552844595), -52, 53)
-    assert x2_str._mpf_ == (0, long(10808639105689190), -53, 53)
+    # x2_str was entered slightly malformed in that the mantissa
+    # was even -- it should be odd and the even part should be
+    # included with the exponent, but this is resolved by normalization
+    # ONLY IF REQUIREMENTS of mpf_norm are met: the bitcount must
+    # be exact: double the mantissa ==> increase bc by 1
+    assert Float(1.2)._mpf_ == mpf
+    assert x2_str._mpf_ == mpf
 
     assert Float((0, long(0), -123, -1)) is S.NaN
     assert Float((0, long(0), -456, -2)) is S.Infinity
     assert Float((1, long(0), -789, -3)) is S.NegativeInfinity
-    assert Float(oo) is Float('+_inf') is S.Infinity
-    assert Float(-oo) is Float('-_inf') is S.NegativeInfinity
+    # if you don't give the full signature, it's not special
+    assert Float((0, long(0), -123)) == Float(0)
+    assert Float((0, long(0), -456)) == Float(0)
+    assert Float((1, long(0), -789)) == Float(0)
 
     raises(ValueError, lambda: Float((0, 7, 1, 3), ''))
 
@@ -506,6 +514,7 @@ def teq(a):
     raises(ValueError, lambda: Float('1_.'))
     raises(ValueError, lambda: Float('1._'))
     raises(ValueError, lambda: Float('1__2'))
+    raises(ValueError, lambda: Float('_inf'))
 
     # allow auto precision detection
     assert Float('.1', '') == Float(.1, 1)
@@ -565,6 +574,13 @@ def teq(a):
     assert same_and_same_prec(Float(pi, 32), pi.evalf(32))
     assert same_and_same_prec(Float(Catalan), Catalan.evalf())
 
+    # oo and nan
+    u = ['inf', '-inf', 'nan', 'iNF', '+inf']
+    v = [oo, -oo, nan, oo, oo]
+    for i, a in zip(u, v):
+        assert Float(i) is a
+
+
 
 @conserve_mpmath_dps
 def test_float_mpf():
@@ -821,13 +837,13 @@ def test_Mul_Infinity_Zero():
 
 def test_Div_By_Zero():
     assert 1/S(0) == zoo
-    assert 1/Float(0) == _inf
+    assert 1/Float(0) == zoo
     assert 0/S(0) == nan
     assert 0/Float(0) == nan
     assert S(0)/0 == nan
     assert Float(0)/0 == nan
     assert -1/S(0) == zoo
-    assert -1/Float(0) == _ninf
+    assert -1/Float(0) == zoo
 
 
 def test_Infinity_inequations():
@@ -1004,12 +1020,14 @@ def test_integer_log():
     assert integer_log(-49, 7) == (0, False)
     assert integer_log(-49, -7) == (2, False)
 
+
 def test_isqrt():
     from math import sqrt as _sqrt
     limit = 17984395633462800708566937239551
     assert int(_sqrt(limit)) == integer_nthroot(limit, 2)[0]
     assert int(_sqrt(limit + 1)) != integer_nthroot(limit + 1, 2)[0]
     assert isqrt(limit + 1) == integer_nthroot(limit + 1, 2)[0]
+    assert isqrt(limit + 1 - S.Half) == integer_nthroot(limit + 1, 2)[0]
     assert isqrt(limit + 1 + S.Half) == integer_nthroot(limit + 1, 2)[0]
 
 
@@ -1620,11 +1638,48 @@ def test_Catalan_EulerGamma_prec():
     assert n._as_mpf_val(20) == f._mpf_
 
 
+def test_bool_eq():
+    assert 0 == False
+    assert S(0) == False
+    assert S(0) != S.false
+    assert 1 == True
+    assert S(1) == True
+    assert S(1) != S.true
+
+
 def test_Float_eq():
+    # all .5 values are the same
+    assert Float(.5, 10) == Float(.5, 11) == Float(.5, 1)
+    # but floats that aren't exact in base-2 still
+    # don't compare the same because they have different
+    # underlying mpf values
     assert Float(.12, 3) != Float(.12, 4)
-    assert Float(.12, 3) == .12
-    assert 0.12 == Float(.12, 3)
+    assert Float(.12, 3) != .12
+    assert 0.12 != Float(.12, 3)
     assert Float('.12', 22) != .12
+    # issue 11707
+    # but Float/Rational -- except for 0 --
+    # are exact so Rational(x) = Float(y) only if
+    # Rational(x) == Rational(Float(y))
+    assert Float('1.1') != Rational(11, 10)
+    assert Rational(11, 10) != Float('1.1')
+    # coverage
+    assert not Float(3) == 2
+    assert not Float(2**2) == S.Half
+    assert Float(2**2) == 4
+    assert not Float(2**-2) == 1
+    assert Float(2**-1) == S.Half
+    assert not Float(2*3) == 3
+    assert not Float(2*3) == S.Half
+    assert Float(2*3) == 6
+    assert not Float(2*3) == 8
+    assert Float(.75) == S(3)/4
+    assert Float(5/18) == 5/18
+    # 4473
+    assert t**2 == t**2.0
+    assert Float(2.) != 3
+    assert Float((0,1,-3)) == S(1)/8
+    assert Float((0,1,-3)) != S(1)/9
 
 
 def test_int_NumberSymbols():
@@ -1693,17 +1748,40 @@ def test_Float_idempotence():
     assert not same_and_same_prec(z, x)
 
 
-def test_comp():
+def test_comp1():
     # sqrt(2) = 1.414213 5623730950...
     a = sqrt(2).n(7)
-    assert comp(a, 1.41421346) is False
-    assert comp(a, 1.41421347)
-    assert comp(a, 1.41421366)
-    assert comp(a, 1.41421367) is False
+    assert comp(a, 1.4142129) is False
+    assert comp(a, 1.4142130)
+    #                  ...
+    assert comp(a, 1.4142141)
+    assert comp(a, 1.4142142) is False
     assert comp(sqrt(2).n(2), '1.4')
     assert comp(sqrt(2).n(2), Float(1.4, 2), '')
-    raises(ValueError, lambda: comp(sqrt(2).n(2), 1.4, ''))
+    assert comp(sqrt(2).n(2), 1.4, '')
     assert comp(sqrt(2).n(2), Float(1.4, 3), '') is False
+    assert comp(sqrt(2) + sqrt(3)*I, 1.4 + 1.7*I, .1)
+    assert not comp(sqrt(2) + sqrt(3)*I, (1.5 + 1.7*I)*0.89, .1)
+    assert comp(sqrt(2) + sqrt(3)*I, (1.5 + 1.7*I)*0.90, .1)
+    assert comp(sqrt(2) + sqrt(3)*I, (1.5 + 1.7*I)*1.07, .1)
+    assert not comp(sqrt(2) + sqrt(3)*I, (1.5 + 1.7*I)*1.08, .1)
+    assert [(i, j)
+            for i in range(130, 150)
+            for j in range(170, 180)
+            if comp((sqrt(2)+ I*sqrt(3)).n(3), i/100. + I*j/100.)] == [
+        (141, 173), (142, 173)]
+    raises(ValueError, lambda: comp(t, '1'))
+    raises(ValueError, lambda: comp(t, 1))
+    assert comp(0, 0.0)
+    assert comp(.5, S.Half)
+    assert comp(2 + sqrt(2), 2.0 + sqrt(2))
+    assert not comp(0, 1)
+    assert not comp(2, sqrt(2))
+    assert not comp(2 + I, 2.0 + sqrt(2))
+    assert not comp(2.0 + sqrt(2), 2 + I)
+    assert not comp(2.0 + sqrt(2), sqrt(3))
+    assert comp(1/pi.n(4), 0.3183, 1e-5)
+    assert not comp(1/pi.n(4), 0.3183, 8e-6)
 
 
 def test_issue_9491():
@@ -1830,22 +1908,10 @@ def __ne__(self, other):
         raises(TypeError, lambda: bar <= n)
 
 def test_NumberSymbol_comparison():
+    from sympy.core.tests.test_relational import rel_check
     rpi = Rational('905502432259640373/288230376151711744')
     fpi = Float(float(pi))
-
-    assert (rpi == pi) == (pi == rpi)
-    assert (rpi != pi) == (pi != rpi)
-    assert (rpi < pi) == (pi > rpi)
-    assert (rpi <= pi) == (pi >= rpi)
-    assert (rpi > pi) == (pi < rpi)
-    assert (rpi >= pi) == (pi <= rpi)
-
-    assert (fpi == pi) == (pi == fpi)
-    assert (fpi != pi) == (pi != fpi)
-    assert (fpi < pi) == (pi > fpi)
-    assert (fpi <= pi) == (pi >= fpi)
-    assert (fpi > pi) == (pi < fpi)
-    assert (fpi >= pi) == (pi <= fpi)
+    assert rel_check(rpi, fpi)
 
 def test_Integer_precision():
     # Make sure Integer inputs for keyword args work
diff --git a/sympy/core/tests/test_power.py b/sympy/core/tests/test_power.py
index 8188a81aaf..5588631ab9 100644
--- a/sympy/core/tests/test_power.py
+++ b/sympy/core/tests/test_power.py
@@ -264,7 +264,7 @@ def test_pow_as_base_exp():
     assert Pow(1, 2, evaluate=False).as_base_exp() == (S(1), S(2))
 
 
-def test_issue_6100_12942():
+def test_issue_6100_12942_4473():
     x = Symbol('x')
     y = Symbol('y')
     assert x**1.0 != x
@@ -273,6 +273,7 @@ def test_issue_6100_12942():
     assert x**1.0 is not True
     assert x is not True
     assert x*y != (x*y)**1.0
+    # Pow != Symbol
     assert (x**1.0)**1.0 != x
     assert (x**1.0)**2.0 == x**2
     b = Basic()
diff --git a/sympy/core/tests/test_relational.py b/sympy/core/tests/test_relational.py
index c09da2dc07..564e7e9cea 100644
--- a/sympy/core/tests/test_relational.py
+++ b/sympy/core/tests/test_relational.py
@@ -14,6 +14,35 @@
 x, y, z, t = symbols('x,y,z,t')
 
 
+def rel_check(a, b):
+    from sympy.utilities.pytest import raises
+    assert a.is_number and b.is_number
+    for do in range(len(set([type(a), type(b)]))):
+        if S.NaN in (a, b):
+            v = [(a == b), (a != b)]
+            assert len(set(v)) == 1 and v[0] == False
+            assert not (a != b) and not (a == b)
+            assert raises(TypeError, lambda: a < b)
+            assert raises(TypeError, lambda: a <= b)
+            assert raises(TypeError, lambda: a > b)
+            assert raises(TypeError, lambda: a >= b)
+        else:
+            E = [(a == b), (a != b)]
+            assert len(set(E)) == 2
+            v = [
+            (a < b), (a <= b), (a > b), (a >= b)]
+            i = [
+            [True,    True,     False,   False],
+            [False,   True,     False,   True], # <-- i == 1
+            [False,   False,    True,    True]].index(v)
+            if i == 1:
+                assert E[0] or (a.is_Float != b.is_Float) # ugh
+            else:
+                assert E[1]
+        a, b = b, a
+    return True
+
+
 def test_rel_ne():
     assert Relational(x, y, '!=') == Ne(x, y)
 
@@ -555,30 +584,32 @@ def test_ineq_avoid_wild_symbol_flip():
 
 def test_issue_8245():
     a = S("6506833320952669167898688709329/5070602400912917605986812821504")
-    q = a.n(10)
-    assert (a == q) is True
-    assert (a != q) is False
-    assert (a > q) == False
-    assert (a < q) == False
-    assert (a >= q) == True
-    assert (a <= q) == True
+    assert rel_check(a, a.n(10))
+    assert rel_check(a, a.n(20))
+    assert rel_check(a, a.n())
+    # prec of 30 is enough to fully capture a as mpf
+    assert Float(a, 30) == Float(str(a.p), '')/Float(str(a.q), '')
+    for i in range(31):
+        r = Rational(Float(a, i))
+        f = Float(r)
+        assert (f < a) == (Rational(f) < a)
+    # test sign handling
+    assert (-f < -a) == (Rational(-f) < -a)
+    # test equivalence handling
+    isa = Float(a.p,'')/Float(a.q,'')
+    assert isa <= a
+    assert not isa < a
+    assert isa >= a
+    assert not isa > a
+    assert isa > 0
 
     a = sqrt(2)
     r = Rational(str(a.n(30)))
-    assert (r == a) is False
-    assert (r != a) is True
-    assert (r > a) == True
-    assert (r < a) == False
-    assert (r >= a) == True
-    assert (r <= a) == False
+    assert rel_check(a, r)
+
     a = sqrt(2)
     r = Rational(str(a.n(29)))
-    assert (r == a) is False
-    assert (r != a) is True
-    assert (r > a) == False
-    assert (r < a) == True
-    assert (r >= a) == False
-    assert (r <= a) == True
+    assert rel_check(a, r)
 
     assert Eq(log(cos(2)**2 + sin(2)**2), 0) == True
 
@@ -758,22 +789,11 @@ def test_issues_13081_12583_12534():
     # pick one such precision and affirm that the reversed operation
     # gives the opposite result, i.e. if x < y is true then x > y
     # must be false
-    p = 20
-    # Rational vs NumberSymbol
-    G = [Rational(pi.n(i)) > pi for i in (p, p + 1)]
-    L = [Rational(pi.n(i)) < pi for i in (p, p + 1)]
-    assert G == [False, True]
-    assert all(i is not j for i, j in zip(L, G))
-    # Float vs NumberSymbol
-    G = [pi.n(i) > pi for i in (p, p + 1)]
-    L = [pi.n(i) < pi for i in (p, p + 1)]
-    assert G == [False, True]
-    assert all(i is not j for i, j in zip(L, G))
-    # Float vs Float
-    G = [pi.n(p) > pi.n(p + 1)]
-    L = [pi.n(p) < pi.n(p + 1)]
-    assert G == [True]
-    assert all(i is not j for i, j in zip(L, G))
+    for i in (20, 21):
+        v = pi.n(i)
+        assert rel_check(Rational(v), pi)
+        assert rel_check(v, pi)
+    assert rel_check(pi.n(20), pi.n(21))
     # Float vs Rational
     # the rational form is less than the floating representation
     # at the same precision
diff --git a/sympy/core/tests/test_sympify.py b/sympy/core/tests/test_sympify.py
index fb917d4dbb..900c6062f3 100644
--- a/sympy/core/tests/test_sympify.py
+++ b/sympy/core/tests/test_sympify.py
@@ -2,7 +2,8 @@
     Function, I, S, N, sqrt, srepr, Rational, Tuple, Matrix, Interval, Add, Mul,
     Pow, Or, true, false, Abs, pi, Range, Xor)
 from sympy.abc import x, y
-from sympy.core.sympify import sympify, _sympify, SympifyError, kernS
+from sympy.core.sympify import (sympify, _sympify, SympifyError, kernS,
+    CantSympify)
 from sympy.core.decorators import _sympifyit
 from sympy.external import import_module
 from sympy.utilities.pytest import raises, XFAIL, skip
@@ -161,11 +162,29 @@ def test_sympify_bool():
 def test_sympyify_iterables():
     ans = [Rational(3, 10), Rational(1, 5)]
     assert sympify(['.3', '.2'], rational=True) == ans
-    assert sympify(tuple(['.3', '.2']), rational=True) == Tuple(*ans)
     assert sympify(dict(x=0, y=1)) == {x: 0, y: 1}
     assert sympify(['1', '2', ['3', '4']]) == [S(1), S(2), [S(3), S(4)]]
 
 
+@XFAIL
+def test_issue_16772():
+    # because there is a converter for tuple, the
+    # args are only sympified without the flags being passed
+    # along; list, on the other hand, is not converted
+    # with a converter so its args are traversed later
+    ans = [Rational(3, 10), Rational(1, 5)]
+    assert sympify(tuple(['.3', '.2']), rational=True) == Tuple(*ans)
+
+
+@XFAIL
+def test_issue_16859():
+    # because there is a converter for float, the
+    # CantSympify class designation is ignored
+    class no(float, CantSympify):
+        pass
+    raises(SympifyError, lambda: sympify(no(1.2)))
+
+
 def test_sympify4():
     class A:
         def _sympy_(self):
diff --git a/sympy/functions/elementary/tests/test_piecewise.py b/sympy/functions/elementary/tests/test_piecewise.py
index 36b3462d1b..7bb7d4b52f 100644
--- a/sympy/functions/elementary/tests/test_piecewise.py
+++ b/sympy/functions/elementary/tests/test_piecewise.py
@@ -14,7 +14,7 @@
 z = symbols('z', nonzero=True)
 
 
-def test_piecewise():
+def test_piecewise1():
 
     # Test canonicalization
     assert Piecewise((x, x < 1), (0, True)) == Piecewise((x, x < 1), (0, True))
@@ -144,8 +144,8 @@ def test_piecewise():
         (x**3/3 + S(4)/3, x < 0),
         (x*log(x) - x + S(4)/3, True))
     p = Piecewise((x, x < 1), (x**2, -1 <= x), (x, 3 < x))
-    assert integrate(p, (x, -2, 2)) == 5/6.0
-    assert integrate(p, (x, 2, -2)) == -5/6.0
+    assert integrate(p, (x, -2, 2)) == S(5)/6
+    assert integrate(p, (x, 2, -2)) == -S(5)/6
     p = Piecewise((0, x < 0), (1, x < 1), (0, x < 2), (1, x < 3), (0, True))
     assert integrate(p, (x, -oo, oo)) == 2
     p = Piecewise((x, x < -10), (x**2, x <= -1), (x, 1 < x))
@@ -546,10 +546,9 @@ def test_piecewise_fold():
 def test_piecewise_fold_piecewise_in_cond():
     p1 = Piecewise((cos(x), x < 0), (0, True))
     p2 = Piecewise((0, Eq(p1, 0)), (p1 / Abs(p1), True))
-    p3 = piecewise_fold(p2)
-    assert(p2.subs(x, -pi/2) == 0.0)
-    assert(p2.subs(x, 1) == 0.0)
-    assert(p2.subs(x, -pi/4) == 1.0)
+    assert p2.subs(x, -pi/2) == 0
+    assert p2.subs(x, 1) == 0
+    assert p2.subs(x, -pi/4) == 1
     p4 = Piecewise((0, Eq(p1, 0)), (1,True))
     ans = piecewise_fold(p4)
     for i in range(-1, 1):
diff --git a/sympy/geometry/tests/test_ellipse.py b/sympy/geometry/tests/test_ellipse.py
index f89dcfd1d7..1c33991366 100644
--- a/sympy/geometry/tests/test_ellipse.py
+++ b/sympy/geometry/tests/test_ellipse.py
@@ -472,7 +472,7 @@ def test_issue_15259():
     assert Circle((1, 2), 0) == Point(1, 2)
 
 
-def test_issue_15797():
+def test_issue_15797_equals():
     Ri = 0.024127189424130748
     Ci = (0.0864931002830291, 0.0819863295239654)
     A = Point(0, 0.0578591400998346)
diff --git a/sympy/geometry/tests/test_line.py b/sympy/geometry/tests/test_line.py
index a83b23e813..2721401844 100644
--- a/sympy/geometry/tests/test_line.py
+++ b/sympy/geometry/tests/test_line.py
@@ -531,8 +531,8 @@ def test_intersection_2d():
         Point2D(n/d*S(3)/2000, -S(497)/10)]
 
 
-@slow
 def test_line_intersection():
+    # see also test_issue_11238 in test_matrices.py
     x0 = tan(13*pi/45)
     x1 = sqrt(3)
     x2 = x0**2
diff --git a/sympy/geometry/tests/test_point.py b/sympy/geometry/tests/test_point.py
index d25264982e..3b8c882df2 100644
--- a/sympy/geometry/tests/test_point.py
+++ b/sympy/geometry/tests/test_point.py
@@ -103,7 +103,7 @@ def test_point():
 
     a, b = Rational(1, 2), Rational(1, 3)
     assert Point(a, b).evalf(2) == \
-        Point(a.n(2), b.n(2))
+        Point(a.n(2), b.n(2), evaluate=False)
     raises(ValueError, lambda: Point(1, 2) + 1)
 
     # test transformations
@@ -179,10 +179,10 @@ def test_point3D():
     assert Point3D(x*(x - 1), y, 2) - Point3D(x**2 - x, y + 1, 1) == \
         Point3D(0, -1, 1)
 
-    a, b = Rational(1, 2), Rational(1, 3)
-    assert Point(a, b).evalf(2) == \
-        Point(a.n(2), b.n(2))
-    raises(ValueError, lambda: Point(1, 2) + 1)
+    a, b, c = Rational(1, 2), Rational(1, 3), Rational(1, 4)
+    assert Point3D(a, b, c).evalf(2) == \
+        Point(a.n(2), b.n(2), c.n(2), evaluate=False)
+    raises(ValueError, lambda: Point3D(1, 2, 3) + 1)
 
     # test transformations
     p = Point3D(1, 1, 1)
@@ -195,7 +195,6 @@ def test_point3D():
     # Test __new__
     assert Point3D(0.1, 0.2, evaluate=False, on_morph='ignore').args[0].is_Float
 
-
     # Test length property returns correctly
     assert p.length == 0
     assert p1_1.length == 0
@@ -351,11 +350,11 @@ def test_arguments():
     # test evaluate=False for ops
     x = Symbol('x')
     a = Point(0, 1)
-    assert a + (0.1, x) == Point(0.1, 1 + x)
+    assert a + (0.1, x) == Point(0.1, 1 + x, evaluate=False)
     a = Point(0, 1)
-    assert a/10.0 == Point(0.0, 0.1)
+    assert a/10.0 == Point(0, 0.1, evaluate=False)
     a = Point(0, 1)
-    assert a*10.0 == Point(0.0, 10.0)
+    assert a*10.0 == Point(0.0, 10.0, evaluate=False)
 
     # test evaluate=False when changing dimensions
     u = Point(.1, .2, evaluate=False)
diff --git a/sympy/matrices/tests/test_matrices.py b/sympy/matrices/tests/test_matrices.py
index 41a5e1d75d..5d56554cfa 100644
--- a/sympy/matrices/tests/test_matrices.py
+++ b/sympy/matrices/tests/test_matrices.py
@@ -3359,9 +3359,13 @@ def test_issue_11238():
     m2 = Matrix([p1 - p0, p2 - p0])
     m3 = Matrix([simplify(p1 - p0), simplify(p2 - p0)])
 
-    assert m1.rank(simplify=True) == 1
-    assert m2.rank(simplify=True) == 1
-    assert m3.rank(simplify=True) == 1
+    # This system has expressions which are zero and
+    # cannot be easily proved to be such, so without
+    # numerical testing, these assertions will fail.
+    Z = lambda x: abs(x.n()) < 1e-20
+    assert m1.rank(simplify=True, iszerofunc=Z) == 1
+    assert m2.rank(simplify=True, iszerofunc=Z) == 1
+    assert m3.rank(simplify=True, iszerofunc=Z) == 1
 
 def test_as_real_imag():
     m1 = Matrix(2,2,[1,2,3,4])
diff --git a/sympy/ntheory/tests/test_factor_.py b/sympy/ntheory/tests/test_factor_.py
index 4c48c4d8d5..075821e3c1 100644
--- a/sympy/ntheory/tests/test_factor_.py
+++ b/sympy/ntheory/tests/test_factor_.py
@@ -112,7 +112,8 @@ def test_multiplicity():
 
 
 def test_perfect_power():
-    assert perfect_power(0) is False
+    raises(ValueError, lambda: perfect_power(0))
+    raises(ValueError, lambda: perfect_power(Rational(25, 4)))
     assert perfect_power(1) is False
     assert perfect_power(2) is False
     assert perfect_power(3) is False
diff --git a/sympy/physics/optics/tests/test_utils.py b/sympy/physics/optics/tests/test_utils.py
index a6e123d6c2..9253e9a3eb 100644
--- a/sympy/physics/optics/tests/test_utils.py
+++ b/sympy/physics/optics/tests/test_utils.py
@@ -1,3 +1,4 @@
+from sympy.core.numbers import comp
 from sympy.physics.optics.utils import (refraction_angle, fresnel_coefficients,
         deviation, brewster_angle, critical_angle, lens_makers_formula,
         mirror_formula, lens_formula, hyperfocal_distance,
@@ -15,6 +16,8 @@
 from sympy.utilities.pytest import raises
 
 
+ae = lambda a, b, n: comp(a, b, 10**-n)
+
 def test_refraction_angle():
     n1, n2 = symbols('n1, n2')
     m1 = Medium('m1')
@@ -63,8 +66,8 @@ def test_refraction_angle():
     assert refraction_angle(r1, 1.33, 1, plane=P) == 0  # TIR
     assert refraction_angle(r1, 1, 1, normal_ray) == \
         Ray3D(Point3D(0, 0, 0), direction_ratio=[1, 1, -1])
-    assert round(refraction_angle(0.5, 1, 2), 5) == 0.24207
-    assert round(refraction_angle(0.5, 2, 1), 5) == 1.28293
+    assert ae(refraction_angle(0.5, 1, 2), 0.24207, 5)
+    assert ae(refraction_angle(0.5, 2, 1), 1.28293, 5)
     raises(ValueError, lambda: refraction_angle(r1, m1, m2, normal_ray, P))
     raises(TypeError, lambda: refraction_angle(m1, m1, m2)) # can add other values for arg[0]
     raises(TypeError, lambda: refraction_angle(r1, m1, m2, None, i))
@@ -72,17 +75,22 @@ def test_refraction_angle():
 
 
 def test_fresnel_coefficients():
-    assert list(round(i, 5) for i in fresnel_coefficients(0.5, 1, 1.33)) == \
-        [0.11163, -0.17138, 0.83581, 0.82862]
-    assert list(round(i, 5) for i in fresnel_coefficients(0.5, 1.33, 1)) == \
-            [-0.07726, 0.20482, 1.22724, 1.20482]
+    assert all(ae(i, j, 5) for i, j in zip(
+        fresnel_coefficients(0.5, 1, 1.33),
+        [0.11163, -0.17138, 0.83581, 0.82862]))
+    assert all(ae(i, j, 5) for i, j in zip(
+        fresnel_coefficients(0.5, 1.33, 1),
+        [-0.07726, 0.20482, 1.22724, 1.20482]))
     m1 = Medium('m1')
     m2 = Medium('m2', n=2)
-    assert list(round(i, 5) for i in fresnel_coefficients(0.3, m1, m2)) == \
-        [0.31784, -0.34865, 0.65892, 0.65135]
-    assert list(list(round(j, 5) for j in i.as_real_imag()) for i in \
-            fresnel_coefficients(0.6, m2, m1)) == \
-        [[-0.23563, -0.97184], [0.81648, -0.57738]]
+    assert all(ae(i, j, 5) for i, j in zip(
+        fresnel_coefficients(0.3, m1, m2),
+        [0.31784, -0.34865, 0.65892, 0.65135]))
+    ans = [[-0.23563, -0.97184], [0.81648, -0.57738]]
+    got = fresnel_coefficients(0.6, m2, m1)
+    for i, j in zip(got, ans):
+        for a, b in zip(i.as_real_imag(), j):
+            assert ae(a, b, 5)
 
 
 def test_deviation():
@@ -99,24 +107,24 @@ def test_deviation():
     assert deviation(r1, 1.33, 1, plane=P) is None  # TIR
     assert deviation(r1, 1, 1, normal=[0, 0, 1]) == 0
     assert deviation([-1, -1, -1], 1, 1, normal=[0, 0, 1]) == 0
-    assert round(deviation(0.5, 1, 2), 5) == -0.25793
-    assert round(deviation(0.5, 2, 1), 5) == 0.78293
+    assert ae(deviation(0.5, 1, 2), -0.25793, 5)
+    assert ae(deviation(0.5, 2, 1), 0.78293, 5)
 
 
 def test_brewster_angle():
     m1 = Medium('m1', n=1)
     m2 = Medium('m2', n=1.33)
-    assert round(brewster_angle(m1, m2), 2) == 0.93
+    assert ae(brewster_angle(m1, m2), 0.93, 2)
     m1 = Medium('m1', permittivity=e0, n=1)
     m2 = Medium('m2', permittivity=e0, n=1.33)
-    assert round(brewster_angle(m1, m2), 2) == 0.93
-    assert round(brewster_angle(1, 1.33), 2) == 0.93
+    assert ae(brewster_angle(m1, m2), 0.93, 2)
+    assert ae(brewster_angle(1, 1.33), 0.93, 2)
 
 
 def test_critical_angle():
     m1 = Medium('m1', n=1)
     m2 = Medium('m2', n=1.33)
-    assert round(critical_angle(m2, m1), 2) == 0.85
+    assert ae(critical_angle(m2, m1), 0.85, 2)
 
 
 def test_lens_makers_formula():
@@ -124,8 +132,8 @@ def test_lens_makers_formula():
     m1 = Medium('m1', permittivity=e0, n=1)
     m2 = Medium('m2', permittivity=e0, n=1.33)
     assert lens_makers_formula(n1, n2, 10, -10) == 5*n2/(n1 - n2)
-    assert round(lens_makers_formula(m1, m2, 10, -10), 2) == -20.15
-    assert round(lens_makers_formula(1.33, 1, 10, -10), 2) == 15.15
+    assert ae(lens_makers_formula(m1, m2, 10, -10), -20.15, 2)
+    assert ae(lens_makers_formula(1.33, 1, 10, -10),  15.15, 2)
 
 
 def test_mirror_formula():
@@ -166,7 +174,7 @@ def test_lens_formula():
 def test_hyperfocal_distance():
     f, N, c = symbols('f, N, c')
     assert hyperfocal_distance(f=f, N=N, c=c) == f**2/(N*c)
-    assert round(hyperfocal_distance(f=0.5, N=8, c=0.0033), 2) == 9.47
+    assert ae(hyperfocal_distance(f=0.5, N=8, c=0.0033), 9.47, 2)
 
 def test_transverse_magnification():
     si, so = symbols('si, so')
diff --git a/sympy/physics/units/tests/test_util.py b/sympy/physics/units/tests/test_util.py
index 9ec68d969e..d2de05e794 100644
--- a/sympy/physics/units/tests/test_util.py
+++ b/sympy/physics/units/tests/test_util.py
@@ -63,7 +63,7 @@ def test_dim_simplify_dimless():
 def test_convert_to_quantities():
     assert convert_to(3, meter) == 3
 
-    assert convert_to(mile, kilometer) == 1.609344*kilometer
+    assert convert_to(mile, kilometer) == 25146*kilometer/15625
     assert convert_to(meter/second, speed_of_light) == speed_of_light/299792458
     assert convert_to(299792458*meter/second, speed_of_light) == speed_of_light
     assert convert_to(2*299792458*meter/second, speed_of_light) == 2*speed_of_light
@@ -71,12 +71,12 @@ def test_convert_to_quantities():
     assert convert_to(2*speed_of_light, meter/second) == 599584916*meter/second
     assert convert_to(day, second) == 86400*second
     assert convert_to(2*hour, minute) == 120*minute
-    assert convert_to(mile, meter) == 1609.344*meter
+    assert convert_to(mile, meter) == 201168*meter/125
     assert convert_to(mile/hour, kilometer/hour) == 25146*kilometer/(15625*hour)
     assert convert_to(3*newton, meter/second) == 3*newton
     assert convert_to(3*newton, kilogram*meter/second**2) == 3*meter*kilogram/second**2
-    assert convert_to(kilometer + mile, meter) == 2609.344*meter
-    assert convert_to(2*kilometer + 3*mile, meter) == 6828.032*meter
+    assert convert_to(kilometer + mile, meter) == 326168*meter/125
+    assert convert_to(2*kilometer + 3*mile, meter) == 853504*meter/125
     assert convert_to(inch**2, meter**2) == 16129*meter**2/25000000
     assert convert_to(3*inch**2, meter) == 48387*meter**2/25000000
     assert convert_to(2*kilometer/hour + 3*mile/hour, meter/second) == 53344*meter/(28125*second)
diff --git a/sympy/printing/tests/test_str.py b/sympy/printing/tests/test_str.py
index d68b5f3685..21ea102f38 100644
--- a/sympy/printing/tests/test_str.py
+++ b/sympy/printing/tests/test_str.py
@@ -512,7 +512,7 @@ def test_Float():
     assert str(pi.evalf(1 + 14)) == '3.14159265358979'
     assert str(pi.evalf(1 + 64)) == ('3.141592653589793238462643383279'
                                      '5028841971693993751058209749445923')
-    assert str(pi.round(-1)) == '0.'
+    assert str(pi.round(-1)) == '0.0'
     assert str((pi**400 - (pi**400).round(1)).n(2)) == '-0.e+88'
 
 
diff --git a/sympy/sets/tests/test_fancysets.py b/sympy/sets/tests/test_fancysets.py
index 2ec8f307fe..92b68d32f7 100644
--- a/sympy/sets/tests/test_fancysets.py
+++ b/sympy/sets/tests/test_fancysets.py
@@ -518,7 +518,10 @@ def test_ComplexRegion_contains():
     r1 = Interval(0, 1)
     theta1 = Interval(0, 2*S.Pi)
     c3 = ComplexRegion(r1*theta1, polar=True)
-    assert 0.5 + 0.6*I in c3
+    assert (0.5 + 6*I/10) in c3
+    assert (S.Half + 6*I/10) in c3
+    assert (S.Half + .6*I) in c3
+    assert (0.5 + .6*I) in c3
     assert I in c3
     assert 1 in c3
     assert 0 in c3
diff --git a/sympy/stats/tests/test_joint_rv.py b/sympy/stats/tests/test_joint_rv.py
index fcb61572c9..71f18a1123 100644
--- a/sympy/stats/tests/test_joint_rv.py
+++ b/sympy/stats/tests/test_joint_rv.py
@@ -1,5 +1,6 @@
 from sympy import (symbols, pi, oo, S, exp, sqrt, besselk, Indexed, Rational,
                     simplify, Piecewise, factorial, Eq, gamma, Sum)
+from sympy.core.numbers import comp
 from sympy.stats import density
 from sympy.stats.joint_rv import marginal_distribution
 from sympy.stats.joint_rv_types import JointRV
@@ -120,11 +121,12 @@ def test_NegativeMultinomial():
     assert simplify(density(N)(x1, x2, x3, x4) -
             p1**x1*p2**x2*p3**x3*p4**x4*(-p1 - p2 - p3 - p4 + 1)**4*g(x1 + x2 +
             x3 + x4 + 4)/(6*f(x1)*f(x2)*f(x3)*f(x4))) == S(0)
-    assert marginal_distribution(C, C[0])(1).evalf().round(2) == 0.33
+    assert comp(marginal_distribution(C, C[0])(1).evalf(), 0.33, .01)
     raises(ValueError, lambda: NegativeMultinomial('b1', 5, [p1, p2, p3, p1_f]))
     raises(ValueError, lambda: NegativeMultinomial('b2', k0, 0.5, 0.4, 0.3, 0.4))
 
-def test_JointPSpace_margial_distribution():
+
+def test_JointPSpace_marginal_distribution():
     from sympy.stats.joint_rv_types import MultivariateT
     from sympy import polar_lift
     T = MultivariateT('T', [0, 0], [[1, 0], [0, 1]], 2)
@@ -132,7 +134,7 @@ def test_JointPSpace_margial_distribution():
         8*polar_lift(x**2/2 + 1)**(S(5)/2))
     assert integrate(marginal_distribution(T, 1)(x), (x, -oo, oo)) == 1
     t = MultivariateT('T', [0, 0, 0], [[1, 0, 0], [0, 1, 0], [0, 0, 1]], 3)
-    assert marginal_distribution(t, 0)(1).evalf().round(1) == 0.2
+    assert comp(marginal_distribution(t, 0)(1).evalf(), 0.2, .01)
 
 
 def test_JointRV():
diff --git a/sympy/stats/tests/test_rv.py b/sympy/stats/tests/test_rv.py
index 778c18c350..b5d24a030f 100644
--- a/sympy/stats/tests/test_rv.py
+++ b/sympy/stats/tests/test_rv.py
@@ -2,6 +2,7 @@
 from sympy import (EmptySet, FiniteSet, S, Symbol, Interval, exp, erf, sqrt,
         symbols, simplify, Eq, cos, And, Tuple, integrate, oo, sin, Sum, Basic,
         DiracDelta, Lambda, log, pi)
+from sympy.core.numbers import comp
 from sympy.stats import (Die, Normal, Exponential, FiniteRV, P, E, H, variance, covariance,
         skewness, density, given, independent, dependent, where, pspace,
         random_symbols, sample, Geometric)
@@ -108,13 +109,14 @@ def test_IndependentProductPSpace():
 def test_E():
     assert E(5) == 5
 
+
 def test_H():
     X = Normal('X', 0, 1)
     D = Die('D', sides = 4)
     G = Geometric('G', 0.5)
     assert H(X, X > 0) == -log(2)/2 + S(1)/2 + log(pi)/2
     assert H(D, D > 2) == log(2)
-    assert H(G).evalf().round(2) == 1.39
+    assert comp(H(G).evalf().round(2), 1.39)
 
 
 def test_Sample():