133

Are there data types with better precision than float?

Mateusz Piotrowski
  • 8,029
  • 10
  • 53
  • 79
kravemir
  • 10,636
  • 17
  • 64
  • 111
  • 5
    This is actually two questions with different answers. 1: double precision values in python are floats, and 2: a better precision data type than float would be decimal. Can questions like this be split somehow? The accepted answer addresses #2, but most upvoted answer addresses #1. – bsplosion Mar 15 '19 at 14:30

5 Answers5

179

Python's built-in float type has double precision (it's a C double in CPython, a Java double in Jython). If you need more precision, get NumPy and use its numpy.float128.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • 22
    Apparently, `numpy.float128` often has 64 bit precision on a 64 bit system. `numpy.float128(1) + numpy.float128(2**-64) - numpy.float128(1)` returns `0.0`. See http://stackoverflow.com/a/29821557/420755 – Jeff Feb 24 '16 at 18:52
  • 1
    0.1 + 0.2 is not exact 0.3 in python, in every other language this is a float problem but never a double problem. Why it is not exact 0.3 in python? – Fusca Software Dec 29 '20 at 04:23
  • 5
    @FuscaSoftware It's a problem in other languages too. IEEE doubles can't represent 0.3 exactly. That sounds like a formatting artifact. – Hans Musgrave Dec 29 '20 at 07:29
  • Funnily enough this was not mentioned in their documentation page, or any other page that speaks about "float precision" in Python. – alexpanter Jan 18 '23 at 21:42
72

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

Jacob
  • 41,721
  • 6
  • 79
  • 81
23

For some applications you can use Fraction instead of floating-point numbers.

>>> from fractions import Fraction
>>> Fraction(1, 3**54)
Fraction(1, 58149737003040059690390169)

(For other applications, there's decimal, as suggested out by the other responses.)

Gareth Rees
  • 64,967
  • 9
  • 133
  • 163
  • 2
    how do I choose between Decimal and Fraction? Fraction seems better since it can represent continuing fractions which I guess Decimal can't? – Janus Troelsen Nov 26 '12 at 13:44
  • 2
    @Janus: consider your requirements, and pick the one that fits them better. Use `Decimal` when you want to work with approximate numbers that have fixed (but configurable) precision. Use `Fraction` when you want to work with exact ratios, and are prepared to put up with their unbounded storage requirements. – Gareth Rees Nov 26 '12 at 17:10
  • Does Fraction support all the operations you can do with float? – danijar Jan 14 '15 at 10:18
20

May be you need Decimal

>>> from decimal import Decimal    
>>> Decimal(2.675)
Decimal('2.67499999999999982236431605997495353221893310546875')

Floating Point Arithmetic

jerboa
  • 1,371
  • 2
  • 12
  • 18
-3

Here is my solution. I first create random numbers with random.uniform, format them in to string with double precision and then convert them back to float. You can adjust the precision by changing '.2f' to '.3f' etc..

import random
from decimal import Decimal

GndSpeedHigh = float(format(Decimal(random.uniform(5, 25)), '.2f'))
GndSpeedLow = float(format(Decimal(random.uniform(2, GndSpeedHigh)), '.2f'))
GndSpeedMean = float(Decimal(format(GndSpeedHigh + GndSpeedLow) / 2, '.2f')))
print(GndSpeedMean)
Bittikettu
  • 29
  • 2
  • 2
    Well. Double precision means double length binary representation of variable compared to binary representation of float. Not two decimal places. – kravemir Mar 31 '15 at 15:27
  • You are right. I might have used bad search criteria when I had this problem myself and this is the outcome. Some others might search this same issue like I did and end up here. Hopefully they find some relief. :) – Bittikettu Apr 02 '15 at 06:18
  • 2
    This is the worst way I can think of to round a float to two decimal places. You should at least use `numpy.floor(100*a)/100` to truncate a number `a` to two decimal places. – Wauzl Dec 16 '20 at 10:59