I have a simple string that I want to read into a float without losing any visible information as illustrated below:
s = ' 1.0000\n'
When I do f = float(s), I get f=1.0
How to trick this to get f=1.0000 ?
Thank you
Direct answer: You can't. Floats are imprecise, by design. While python's floats have more than enough precision to represent 1.0000, they will never represent a "1-point-zero-zero-zero-zero". Chances are, this is as good as you need. You can always use string formatting, if you need to display four decimal digits.
print '%.3f' % float(1.0000)
Indirect answer: Use the decimal module.
from decimal import Decimal
d = Decimal('1.0000')
The decimal package is designed to handle all these issues with arbitrary precision. A decimal "1.0000" is exactly 1.0000, no more, no less. Note, however, that complications with rounding means you can't convert from a float directly to a Decimal; you have to pass a string (or an integer) to the constructor.
Decimal class) use an internal variable to keep track of how many digits of precision are desired, and reproduce that many digits on output, but otherwise they would be in exactly the same boat.Decimal class may be a decimal floating point system, the fact is it does support "exact unrounded decimal arithmetic". And it seems that an internal variable to track the precision is exactly what the original poster was looking for.>>> 1.0 == 1.00 == 1.000
True
In other words, you're losing no info -- Python considers trailing zeros in floats' decimal parts to be irrelevant. If you need to keep track very specifically of "number of significant digits", that's also feasible, but you'll need to explain to us all exactly what you're trying to accomplish beyond Python's normal float (e.g., would decimal in the Python standard library have anything to do with it? etc, etc...).
Decimal probably is the answer you want.Indulge me while I reinvent the wheel a little bit! ;)
Should you want the reprsentation of the object (the way it is displayed in the shell) to have the form 1.0000 then you may need to change the __repr__ method of the float. If you would like the object to be printed to a file or screen you will need to change the __str__ method. Here is a class that will do both.
class ExactFloat(float):
def __repr__(self):
return '%.4f' % self
__str__ = __repr__
# usage of the shiny new class to follow..
>>> f = ExactFloat(' 1.0000\n')
>>> f
1.0000
>>> print f
1.0000
Now there are also a myriad of other better ways to do this, but like I said, I love
re-inventing wheels :)
Here's an even shinier version of @Simon Edwards' ExactFloat, that counts the number of digits after the period and displays that number of digits when the number is converted to a string.
import re
class ExactFloat(float):
def __init__(self, str_value):
float.__init__(self, str_value)
mo = re.match("^\d+\.(\d+)", str_value)
self.digits_after_period = len(mo.group(1))
def __repr__(self):
return '%.*f' % (self.digits_after_period, self)
def __str__(self):
return self.__repr__()
print ExactFloat("1.000")
print ExactFloat("1.0")
print ExactFloat("23.234500")
Example:
$ python exactfloat.py
1.000
1.0
23.234500
1.0 === 1.00001.0000for?1.0 !== 1.000in all circumstances. Statisticians would see a very different meaning between the two in terms of precision.