1

I need to make computations in the highest possible precision, regardless if the arguments passed are integers, floats or whatever numbers. One way I can think of this is:

import numpy as np
def foo(x, y, z)
a = (np.float64)0
a = x + y * z

I can see a couple of problems with this: 1) I think I need to convert the inputs, not the result for this to work 2)looks ugly (the first operation is a superfluous C-style declaration).

How can I pythonically perform all calculations in the highest available precision, and then store the results in the highest available precision (which is IMO numpy.float64)?

Vorac
  • 8,726
  • 11
  • 58
  • 101
  • 3
    http://stackoverflow.com/a/11008311/846892 – Ashwini Chaudhary Jun 03 '13 at 08:28
  • @Ashwini Chaudhary, woops, so my example won't work at all! So how should I doit, then? – Vorac Jun 03 '13 at 08:34
  • 1
    If x, y and z are integers, you get an integer back. That's the highest precision. If x, y and z are (Python) floats, you get a float back, which is the highest precision (and, in fact, a C double, so 64bit float). There is no need to declare/convert to a precision, because Python does that for you. –  Jun 03 '13 at 08:38
  • @Evert, results in integers in unacceptable. I know I can multiply everything by 1.0 to get floating point precision. I am looking for a better way. – Vorac Jun 03 '13 at 08:42
  • 1
    Why are result in integers unacceptable? You input integers, so you'd get integers back, which, I'd say, have unlimited precision (and multiplying everything by 1.0 *lowers* the precision). I don't understand your use case, but I think your actual question is different than the one above. –  Jun 03 '13 at 09:36
  • Compare `10**18 + 2` and `1.0e18 + 2.0` - which is a more precise calculation? – detly Jun 03 '13 at 09:51
  • @ Evert, hmm, you make a good point. My problem is rounding e.g. `3/2` – Vorac Jun 03 '13 at 09:54
  • @Vorac I'd assume you have `from __future__ import division`, or are otherwise using Python 3. Once integer division is out of the way, you could (only where necessary) convert to eg `np.longdouble`, but I wouldn't do it inside the function: `a = foo(x,y,z)/np.longdouble(2)` for example. And as mentioned, there is `Decimal`, but that might be too slow for your purposes (though your `foo` function isn't very numpy-style, so perhaps speed isn't an issue). –  Jun 03 '13 at 15:26

2 Answers2

2

To me the obvious answer is Decimal, unless the function needs to be very fast.

import decimal
# set the precision to double that of float64.. or whatever you want.
decimal.setcontext(decimal.Context(prec=34))
def foo(x, y, z)
    x,y,z = [decimal.Decimal(v) for v in (x,y,z)] 
    a = x + y * z
    return a  # you forgot this line in the original code.

If you want a conventional 64bit float, you can just convert the return value to that: return float(a)

kampu
  • 1,391
  • 1
  • 10
  • 14
1

You can declare variable but You can try to force it to be expected type

import numpy as np
def foo(*args):
    x, y, z = map(np.longdouble, args)
    return x + y * z

foo(0.000001,0.000001, 0.00000000001)
oleg
  • 4,082
  • 16
  • 16
  • It needs to be clarified that `float128` is not reliable. It may produce 128-bit precision, or only 64bit precision, according to the platform and the exact operation. – kampu Jun 03 '13 at 09:31
  • 2
    also `longdouble` [is the preferred name](http://stackoverflow.com/questions/9062562/what-is-the-internal-precision-of-numpy-float128) and leads to less headaches. On Linux it's equiv to `float128`, on Windows it's equivalent to `float96` (on Windows, `float128` has problems.) – kampu Jun 03 '13 at 09:42