On Tue, 18 May 2021 at 15:56, Paul Moore <p.f.mo...@gmail.com> wrote: > > On Tue, 18 May 2021 at 15:16, Martin Teichmann > <martin.teichm...@gmail.com> wrote: > > > > Because reality. People would like to write 1/2 * m * v**2 to mean the > > obvious thing, without having to think about the details. And there are > > many people like this, this is why it shows up on this mailing list > > regularly. I have never felt the urge to write two/three * m * v**two. > > I'd actually prefer to write (m*v**2)/2. Or (m/2)*v**2. But those > wouldn't work, the way you describe your proposal. And I'd be very > concerned if they behaved differently than 1/2 * m * v**2...
In SymPy these do behave differently right now: >>> from sympy import symbols >>> m, v = symbols('m, v') >>> (m*v**2)/2 m*v**2/2 >>> (m/2)*v**2 m*v**2/2 >>> 1/2 * m * v**2 0.5*m*v**2 The problem is that while SymPy expressions can define __div__(self, int) to be exact there isn't a way for SymPy to hook into an expression like 1/2 which is just a Python expression using the int type whose __div__ returns floats. SymPy itself treats floats as being different from the exact rational numbers that they represent which is important for users who *do* want to use floats (although I think many users do this just because they want decimal display without understanding the issues that imprecise arithmetic can bring). There is a function in sympy that can "convert" a float to rational with heuristics that allow it to undo decimal-to-binary rounding errors e.g.: >>> from sympy import nsimplify >>> nsimplify(1/2 * m * v**2) m*v**2/2 >>> nsimplify(0.1) 1/10 Note that the Python float 0.1 is not exactly equal to the rational number 1/10 which can not be represented exactly in binary floating point. So that is not an exact conversion although it is necessarily within 1 ulp (in this case). It would be possible to have a mode in SymPy that can do this automatically but then some people wouldn't want that so it possibly shouldn't be on by default. Really there is no way to get around the fact that sometimes you want to use floating point and sometimes you want exact rational arithmetic so both need to be possible in some way. Some other programming languages have special syntax for rational numbers e.g. 1//2 in Julia or 1%2 in Haskell but I don't know of a programming language that uses 1/2 syntax for rational numbers apart from things like Maple/Mathematica. I think that Matlab just does the equivalent of nsimplify above so you can do e.g. sym(1/3) and get 1/3 as an exact rational number even though the original Matlab expression 1/3 gives an approximate floating point result. The Matlab docs acknowledge that this is not always reliable though (the suggestion is to use 1/sym(3) instead): """ Use sym on subexpressions instead of the entire expression for better accuracy. Using sym on entire expressions is inaccurate because MATLAB first converts the expression to a floating-point number, which loses accuracy. sym cannot always recover this lost accuracy. """ https://uk.mathworks.com/help/symbolic/sym.html#bu1rs8g-1 I think that maybe the best solution here is something more like a domain-specific language that can be used with ipython/jupyter as an alternative profile. In the DSL 1/2 could be a Fraction and 2x^2 could be the equivalent of 2*x**2 etc. You'd probably want to be able to write things like √2 and x'' and so on. Maybe you could have a better syntax for creating matrices than the clunky list of lists. Basically there are lots of things that you can't quite do in Python but that you might want to do if you were making a language specifically for the purpose of doing stuff with equations. -- Oscar _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/ZHFSDQKDVD7SRREWHC4XEC5KACKILHZC/ Code of Conduct: http://python.org/psf/codeofconduct/