31

What is the proper/accepted way to print and convert a numpy.float64 to a string? I've noticed just using print or str() will lose some precision. However, repr maintains the full precision. For example:

>>> import numpy
>>> print numpy.float64('6374.345407799015')
6374.3454078
>>> print repr(numpy.float64('6374.345407799015'))
6374.3454077990154
  1. I assume that just calling print turns into calling str() on the float64 object. So is __str__() for numpy.float64 implemented with something like '%s' % (float(self)) or somehow casts the float64 with Python's built-in float()? I tried to quickly look around the numpy source for this but wasn't immediately obvious what was happening.

  2. I've always thought repr() should return valid Python code that could be used by eval() to re-create the object. Is this an accepted convention? Luckily in this case numpy does not follow this convention because repr() returns just the raw number as a string instead of something like "numpy.float64('6374.345407799015')".

So, all of this confuses me. What is the correct way to convert a numpy.float64 to a string and/or print it while guaranteeing you always have the same, full precision?

durden2.0
  • 9,222
  • 9
  • 44
  • 57
  • It's also worth noting that calling `repr()` actually results in MORE precision than the original string that was used to create the float64 object in the first place. What's the story there? – durden2.0 Oct 18 '12 at 13:54
  • 1
    In response to your comment, Note that floating point numbers can't represent every number exactly. In other words, you're asking for the number: `'6374.345407799015'`, but that can't be represented by a float64 number, so numpy (following the IEEE standard) picks the next closest thing which happens to be `6374.3454077990154`. – mgilson Oct 18 '12 at 14:05
  • 1
    Finally, I would say that the best way to turn a `float64` object into a string which is full precision is to use `repr`. If you look at the python data-model, it recommends that `__repr__` for an object should provide sufficient information to reconstruct the object (if possible). – mgilson Oct 18 '12 at 14:09
  • 1
    @mgilson Ok, thanks for the update. I understand the reason for the extra precision just because of floating point representations in general. – durden2.0 Oct 18 '12 at 14:10
  • @mgilson I can see that `repr()` works and that Python recommends using `__repr__` to reconstruct the object. However, I always thought it should return valid Python code to actually build the object. So, by this logic `__repr__` should return a string with the type, like my example above, `"numpy.float64('6374.345407799015')"`. I'm glad numpy doesn't do this in this particular case. However, is my understanding of `__repr__` return value incorrect and why? – durden2.0 Oct 18 '12 at 14:13
  • I suppose this is a matter of how you interpret the [docs](http://docs.python.org/reference/datamodel.html#object.__repr__). Specifically, it says that "the string should be a valid python expression which can be used to recreate the object given and appropriate environment if possible". You're assuming the appropriate environment is `eval`, but it's just as reasonable to assume the environment is `np.float64` IMHO. – mgilson Oct 18 '12 at 14:19

2 Answers2

12

The astype method works well:

>>> numpy.float64('6374.345407799015').astype(str)
'6374.345407799015'
Rahiel Kasim
  • 370
  • 3
  • 8
10

Look into numpy.set_printoptions. Specifically,

numpy.set_printoptions(precision=15)
reptilicus
  • 10,290
  • 6
  • 55
  • 79
  • 7
    You can't see it, but I already posted (and deleted) this answer. The problem is that this only changes the representation of the values when they are packed into an array. – mgilson Oct 18 '12 at 14:03
  • Right, I tried this and it does indeed only deal with numpy.ndarray(). This has no effect on a single numpy.float64. Still good to know though! – durden2.0 Oct 18 '12 at 14:10
  • @reptilicus -- I was pretty surprised (and disappointed) when it didn't work. – mgilson Oct 18 '12 at 14:11
  • 6
    is precision=15 sufficient to exactly represent float64 numbers? – endolith Jul 12 '14 at 03:08
  • @mgilson It's worse than that. It only works on arrays having `ndim>1` – Neil G May 18 '16 at 01:16
  • 1
    @endolith: if you run [np.finfo(np.float)](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.finfo.html), you should get something like `finfo(resolution=1e-15, min=-1.7976931348623157e+308, max=1.7976931348623157e+308, dtype=float64)`. The `resolution` probably corresponds to the max precision. – Yibo Yang Jan 22 '18 at 01:05