2

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

5
  • 6
    1.0 === 1.0000 Commented Sep 22, 2009 at 5:14
  • This is a substantially different question than you originally asked. Commented Sep 22, 2009 at 5:30
  • True, whitespaces come into action, however by visible I only meant the digits. Commented Sep 22, 2009 at 6:02
  • 2
    what do you want to use 1.0000 for? Commented Sep 22, 2009 at 10:46
  • @Gumbo, 1.0 !== 1.000 in all circumstances. Statisticians would see a very different meaning between the two in terms of precision. Commented Mar 10, 2011 at 18:25

4 Answers 4

9

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.

Sign up to request clarification or add additional context in comments.

2 Comments

The precision or imprecision of floats has nothing to do with it. Floating-point representations (by definition) are implemented in essentially the equivalent of scientific notation: with a mantissa and exponent. Since every number is stored as 0.XXXXX times 2 to the YYYY power, decimal places on the right side of the decimal point are meaningless. Base-10 floating point systems (like the Python 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.
I wasn't using "precision" in the strictest sense, but in the "significant digits to the right of the decimal" sense. And while the Python 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.
5
>>> 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...).

5 Comments

I know they are equal that is why I explicitly used the word "visible". I just want to preserve the zeros to comply with my special header standards. If I don't do these in the reading step, I will have to while re-creating the same header using this information. There it is easy, just to use formatting operators for print. Thanks for the explanation.
@gsever: If you're trying to round-trip a number with exact formatting, perhaps it would be easiest just to store both the input string and the floating point representation? However, if you're not doing any fancy math on the value, I think Decimal probably is the answer you want.
No, 1.0 != 1.00 at least in a scientific term. 1.00 has a precision of +-0.01, while 1.0 has a precision of +-0.1
@dalloliogm: it's a question of presentation (read string formatting), not of nulls' importance.
@dalloliogm, the mathematical theory of real numbers (underlying anything from high-school algebra to calculus etc) does not have the concept of "precision" (or "significant digits" or "tolerance" any equivalent simplification of interval-arithmetic). No doubt in science and engineering we do need to augment measurements with error bounds, fraught as it may be with difficulties, but, as a notation for that, declaring the number of trailing zeros to be significant is no help. If a=1.0 and b=1.00, what's a+b? a-b? a*b? a/b? If we can't even do THIS, what good is it at all?!
1

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 :)

1 Comment

I share your sentiments on your reinvention on the wheel since I have done the same thing today. See stackoverflow.com/questions/1449139/simple-object-recognition. To me a very elegant solution, however we might need to add some spices to make it more generic. Probably I will forget about the 0's and later use @Chris B. suggested.
1

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 Comment

This is shining indeed. Thank you for your time for creating this nice example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.