
Common Lisp: Numbers - tosh
https://lispcookbook.github.io/cl-cookbook/numbers.html
======
reikonomusha
The COMPUTABLE-REALS [0] package from the article is interesting because it
lets you change the precision even _after_ a computation is “performed”. It
basically builds up lazy representations of computations that can (internally)
recompute to any precision specified. You do all of your arithmetic as normal
and only until you need to do something with an actual decimal representation
do you “request” it. You grab the actual approximation as a decimal number
with the APPROX-R function, which provides as many digits as you please. There
is _no_ need to re-run all of your code which produced the (computable) number
in the first place to reapproximate at higher precision.

This all directly falls out of a mathematical formalism called “computable
real numbers” [1] which are the (countable!) set of real numbers for which an
algorithm exists to compute the digits to any desired precision. (Usually
binary digits are the standard way to write out the definition of a computable
number.)

[0] [https://github.com/stylewarning/computable-
reals](https://github.com/stylewarning/computable-reals)

[1]
[https://en.m.wikipedia.org/wiki/Computable_number](https://en.m.wikipedia.org/wiki/Computable_number)

~~~
mehrdadn
I don't understand how this is supposed to work. For one thing iterative code
wouldn't even do the same number of iterations when you change the desired
precision, so merely plugging in higher precision numbers wouldn't give the
higher precision approximation you'd be looking for. You'd have to actually
re-execute the entire code with higher precision numbers so that intermediate
control flow decisions use those numbers instead too, right?

~~~
Veedrac
Generally, precision is pulled on-demand, as it is needed. If you compare two
values as x < y, x and y will be evaluated to higher and higher precision
until the answer is unambiguous. This can be an issue if the values are equal,
since they often cannot be proven to be equal, so the evaluation may just
outright fail to terminate.

~~~
mehrdadn
That doesn't address the situation I outlined?

~~~
rocqua
You store the expression. Because that expression is a computable real, you
can calculate it to arbitrary precision.

This is quite inefficient for things like summing over a list. Or really, any
kind of accumulation.

------
mmoez
It is worth noting that most scripting languages today are still restricted by
64-bit integers and IEEE floating points limitations.

Python and Ruby are probably the only popular ones that ship by default with
unlimited precision integers.

For arbitrary precision reals in Python, there is mpmath
[http://mpmath.org/](http://mpmath.org/) . There is also the standard decimal
module which "provides support for fast correctly-rounded decimal floating
point arithmetic" :
[https://docs.python.org/3/library/decimal.html](https://docs.python.org/3/library/decimal.html)

~~~
m4r35n357
For MP work in Python, gmpy2 -
[https://pypi.org/project/gmpy2/](https://pypi.org/project/gmpy2/) comes with
a much better selection of MP functions, backed by MPFR, MPC.

Also, the buit-in Decimal class is horribly slow by comparison to gmpy2.

~~~
baruchel
Purpose of the Decimal module is not really arbitrary precision computation
but rather exact computation on decimal numbers wherever it matters (financial
arithmetic, etc.). This module should never be used for scientific purposes.

------
gibsonf1
I also highly recommend the rtg-math commonlisp library (ql:quickload :rtg-
math) [https://github.com/cbaggers/rtg-math](https://github.com/cbaggers/rtg-
math)

Incredibly fast with support for quaternions / spherical coordinate systems
etc

------
pfdietz
A nice thing about Common Lisp's unlimited precision integer is it made
testing a Common Lisp compiler much easier.

One can easily generate random integer-valued lisp forms without having to do
much checking that integers are in range. In C or other languages with bounded
integer size it's much tougher (see Regehr et al.'s Csmith). It's also tough
to reduce a failing test case without introducing bad behavior in C; in Lisp
it's straightfoward.

