Hello,
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
Hello,
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.
>>> 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...).
Hi gsever
,
Indulge me while I reinvent the wheel a little bit! ;)
Should you want the repr
sentation 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