Python Floating Number

python floating number

Floating point numbers are an approximation, they cannot store decimal numbers exactly. Because they try to represent a very large range of numbers in only 64 bits, they must approximate to some extent.

It is very important to be aware of this, because it results in some weird side-effects. For example, you might very reasonably think that the sum of ten lots of 0.1 would be 1.0. While this seems logical, it is also wrong when it comes to floating point:

>>> f = 0.0
>>> for _ in range (10):
... f += 0.1
...
>>> print f == 1.0
False
>>> f
0.99999999999999989
>>> str(f)
1.0

You might think that n / m * m == n. Once again, floating-point world disagrees:

>>> (1.0 / 103.0) * 103.0
0.99999999999999989

Or perhaps just as strangely, one might think that for all n, n + 1 != n. In floating point land, numbers just don't work like this:

>>> 10.0**200
9.9999999999999997e+199
>>> 10.0**200 == 10.0**200 + 1
True
# How much do we have to add to 10.0**200 before its
# floating point representation changes?
>>> 10.0**200 == 10.0**200 + 10.0**183
True
>>> 10.0**200 == 10.0**200 + 10.0**184
False

See What every computer scientist should know about floating point numbers for an excellent summary of the issues.

If you need exact decimal representation, check out the decimal module, part of the python standard library since 2.4. It allows you to specify the number of significant figures. The downside is, it is much slower than floating point, because floating point operations are implemented in hardware whereas decimal operations happen purely in software. It also has its own imprecision issues, but if you need exact representation of decimal numbers (e.g. for a financial application) it's ideal.

For example:

>>> 3.14
3.1400000000000001
>>> import decimal
>>> decimal.Decimal('3.14')
>>> print decimal.Decimal('3.14')
3.14
# change the precision:
>>> decimal.getcontext().prec = 6
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.142857')
>>> decimal.getcontext().prec = 28
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1428571428571428571428571429')

Floating Point Numbers

Basically, the computer's floating point calculations have rounding errors. So if you perform 1.*1000./1000., you can end up with 1.0000004 or something like that. It is what the computer stores in the memory. However, you probably don't want to see 1.0000004 as a result of that calculation. So when you print the result, the computer does the rounding, and you will get simply 1. But you have to know that it is not the real value in the computer's memory - it is only a comfortable visualization of your actual floating point number.

How to extract a floating number from a string

If your float is always expressed in decimal notation something like

>>> import re
>>> re.findall("\d+\.\d+", "Current Level: 13.4db.")
['13.4']

may suffice.

A more robust version would be:

>>> re.findall(r"[-+]?(?:\d*\.*\d+)", "Current Level: -13.2db or 14.2 or 3")
['-13.2', '14.2', '3']

If you want to validate user input, you could alternatively also check for a float by stepping to it directly:

user_input = "Current Level: 1e100 db"
for token in user_input.split():
try:
# if this succeeds, you have your (first) float
print(float(token), "is a float")
except ValueError:
print(token, "is something else")

# => Would print ...
#
# Current is something else
# Level: is something else
# 1e+100 is a float
# db is something else

How to format a floating number to fixed width in Python

numbers = [23.23, 0.1233, 1.0, 4.223, 9887.2]                                                                                                                                                   

for x in numbers:
print("{:10.4f}".format(x))

prints

   23.2300
0.1233
1.0000
4.2230
9887.2000

The format specifier inside the curly braces follows the Python format string syntax. Specifically, in this case, it consists of the following parts:

  • The empty string before the colon means "take the next provided argument to format()" – in this case the x as the only argument.
  • The 10.4f part after the colon is the format specification.
  • The f denotes fixed-point notation.
  • The 10 is the total width of the field being printed, lefted-padded by spaces.
  • The 4 is the number of digits after the decimal point.

Python 3 Float Decimal Points/Precision

In a word, you can't.

3.65 cannot be represented exactly as a float. The number that you're getting is the nearest number to 3.65 that has an exact float representation.

The difference between (older?) Python 2 and 3 is purely due to the default formatting.

I am seeing the following both in Python 2.7.3 and 3.3.0:

In [1]: 3.65
Out[1]: 3.65

In [2]: '%.20f' % 3.65
Out[2]: '3.64999999999999991118'

For an exact decimal datatype, see decimal.Decimal.

Does Python float function automatically recognize numbers?

In your loop, you call input() twice. Each time you get a single line of the input, so the two values corresponding to the student are both read in a single pass of the loop:

for _ in range(int(input())):
name = input() # get the name
score = float(input()) # get the score, and convert it to a number

Only the second input line, which represents the student's score, gets passed to float. If you passed the student's name (from the previous line) to float, you'd get an exception unless the student had a very unconventional name (like 'Nan' or 'Inf').

Double precision floating values in Python?

Decimal datatype

  • Unlike hardware based binary floating point, the decimal module has a user alterable precision (defaulting to 28 places) which can be as large as needed for a given problem.

If you are pressed by performance issuses, have a look at GMPY

How does python handle very small float numbers?

Your test involves a double rounding and is finding the number 2−53+2−105.

Many Python implementations use the IEEE-754 binary64 format. (This is not required by the Python documentation.) In this format, the significand (fraction portion) of a floating-point number has 53 bits. (52 are encoded in a primary significand field. 1 is encoded via the exponent field.) For numbers in the interval [1, 2), the significand is scaled (by the exponent portion of the floating-point representation) so that its leading bit corresponds to a value of 1 (20). This means is trailing bit corresponds to a value of 2−52.

Thus, the difference between 1 and the next number representable in this format is 2−52—that is the smallest change that can be made in the number, by increasing the low bit.

Now, suppose x contains 1. If we add 2−52 to it, we will of course get 1+2−52, since that result is representable. What happens if we add something slightly smaller, say ¾•2−52? In this case, the real-number result, 1+¾•2−52, is not representable. It must be rounded to a representable number. The common default rounding method is to round to the nearest representable number. In this case, that is 1+2−52.

Thus, adding to 1 some numbers smaller than 2−52 still produces 1+2−52. What is the smallest number we can add to 1 and get this result?

In case of ties, where the real-number result is exactly halfway between two representable numbers, the common default rounding method uses the one with the even low bit. So, with a choice between 1 (trailing bit 0) and 1+2−52 (trailing bit 1), it chooses 1. That means if we add ½•2−52 to 1, it will produce 1.

If we add any number greater than ½•2−52 to 1, there will be no tie; the real-number result will be nearer to 1+2−52, and that will be the result.

The next question is what is the smallest number greater than ½•2−52 (2−53) that we can add to 1? If the number has to be in the IEEE-754 binary64 format, it is limited by its significand. With the leading bit scaled to represent 2−53, the trailing bit represents 2−53−52 = 2−105.

Therefore, 2−53+2−105 is the smallest binary64 value we can add to 1 to get 1+2−52.

As your program tests values, it works with a decimal numeral. That decimal numeral is converted to the floating-point format and then added to 1. So it is finding the smallest number in the floating-point format that produces a sum greater than 1, and that is the number described above, 2−53+2−105. Its value in decimal is 1.110223024625156663683148108873914908082588325435348386438505485784844495356082916259765625•10−16.



Related Topics



Leave a reply



Submit