709

Is there an easy way with Python f-strings to fix the number of digits after the decimal point? (Specifically f-strings, not other string formatting options like .format or %)

For example, let's say I want to display 2 digits after the decimal place.

How do I do that? Let's say that

a = 10.1234
Nicolas Gervais
  • 28,901
  • 11
  • 96
  • 121
GafferMan2112
  • 7,235
  • 3
  • 9
  • 9

8 Answers8

1099

Include the type specifier in your format expression:

>>> a = 10.1234
>>> f'{a:.2f}'
'10.12'
Omry Yadan
  • 28,343
  • 17
  • 59
  • 81
Robᵩ
  • 154,489
  • 17
  • 222
  • 296
  • 71
    None of the f-string formatting examples I have found, including the PEP, show you can use the type specifier. I guess I should have assumed that, but the docs calling it out would be nice. – GafferMan2112 Jul 26 '17 at 22:40
  • 3
    You are right, most of the examples don't have a format specifier. In the PEP, the hex example does: `f'input={value:#06x}'`, and the datetime examples do: `{anniversary:%A, %B %d, %Y}` and `{date:%A}`. I think the key explanation is in the [Code Equivalence](https://www.python.org/dev/peps/pep-0498/#id28) section. – Robᵩ Jul 26 '17 at 22:58
  • 33
    Oh man, this is gorgeous and simple. Why did it take me over 45 whole seconds to find this answer? Up ya game, Google. – Matt Fletcher Dec 12 '17 at 14:42
  • 11
    also note that without f if you write - f'{a:.2}' it will count total number of digits and answer will be 10 – Drako Jul 09 '19 at 12:34
  • the default behavior (right now in 3.8) for me seems to be to format floats in exponent notation if you're _also_ using the precision specifier. So yeah, you'll need to provide an explicit `f` to force a fixed point representation. – linstantnoodles Jul 28 '20 at 13:14
  • copying and pasting this directly into an interactive session gives me a syntax error on python 3.5.2. ```>>> a = 10.1234 >>> f'{a:.2f}' File "", line 1 f'{a:.2f}' ^ SyntaxError: invalid syntax``` – tarabyte Sep 29 '20 at 18:16
  • 4
    @tarabyte - f-strings were introduced in 3.6. That syntax wasn't present in 3.5.2 https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-pep498 – Robᵩ Sep 30 '20 at 01:38
  • Here's a direct link to the language that format specifiers use: https://docs.python.org/3.8/library/string.html#formatspec – Ari Sweedler May 11 '21 at 21:06
  • https://zetcode.com/python/fstring/ – Say OL Oct 07 '21 at 06:43
215

When it comes to float numbers, you can use format specifiers:

f'{value:{width}.{precision}}'

where:

  • value is any expression that evaluates to a number
  • width specifies the number of characters used in total to display, but if value needs more space than the width specifies then the additional space is used.
  • precision indicates the number of characters used after the decimal point

What you are missing is the type specifier for your decimal value. In this link, you an find the available presentation types for floating point and decimal.

Here you have some examples, using the f (Fixed point) presentation type:

# notice that it adds spaces to reach the number of characters specified by width
In [1]: f'{1 + 3 * 1.5:10.3f}'
Out[1]: '     5.500'

# notice that it uses more characters than the ones specified in width
In [2]: f'{3000 + 3 ** (1 / 2):2.1f}' 
Out[2]: '3001.7'

In [3]: f'{1.2345 + 4 ** (1 / 2):9.6f}'
Out[3]: ' 3.234500'

# omitting width but providing precision will use the required characters to display the number with the the specified decimal places
In [4]: f'{1.2345 + 3 * 2:.3f}' 
Out[4]: '7.234'

# not specifying the format will display the number with as many digits as Python calculates
In [5]: f'{1.2345 + 3 * 0.5}'
Out[5]: '2.7344999999999997'
lmiguelvargasf
  • 51,786
  • 40
  • 198
  • 203
  • 1
    @Bouncner [no](https://docs.python.org/3.6/library/string.html#formatspec). – iacob Jun 09 '21 at 13:20
  • where can i find what types of round use format-specifier method, thanks. i know by testing it "round to nearest with ties going away from zero" it is known as ROUND_HALF_UP. i can't find any information about the round strategy that use format-specifier in the doc. – christianbueno.1 Jun 15 '21 at 16:10
84

Adding to Robᵩ's answer: in case you want to print rather large numbers, using thousand separators can be a great help (note the comma).

>>> f'{a*1000:,.2f}'
'10,123.40'

And in case you want to pad/use a fixed width, the width goes before the comma:

>>> f'{a*1000:20,.2f}'
'           10,123.40'
Bouncner
  • 1,634
  • 17
  • 19
62

Adding to Rob's answer, you can use format specifiers with f strings (more here).

  • You can control the number of decimals:
pi = 3.141592653589793238462643383279

print(f'The first 6 decimals of pi are {pi:.6f}.')
The first 6 decimals of pi are 3.141593.
  • You can convert to percentage:
grade = 29/45

print(f'My grade rounded to 3 decimals is {grade:.3%}.')
My grade rounded to 3 decimals is 64.444%.
  • You can do other things like print constant length:
from random import randint
for i in range(5):
    print(f'My money is {randint(0, 150):>3}$')
My money is 126$
My money is   7$
My money is 136$
My money is  15$
My money is  88$
  • Or even print with a comma thousand separator:
print(f'I am worth {10000000000:,}$')
I am worth 10,000,000,000$
Nicolas Gervais
  • 28,901
  • 11
  • 96
  • 121
40

Consider:

>>> number1 = 10.1234
>>> f'{number1:.2f}'
'10.12'
Syntax:
"{" [field_name] ["!" conversion] [":" format_spec] "}"
Explanation:
# Let's break it down...
#       [field_name]     => number1
#       ["!" conversion] => Not used
#       [format_spec]    => [.precision][type] 
#                        => .[2][f] => .2f  # where f means Fixed-point notation

Going further, Format strings have the below syntax. As you can see there is a lot more that can be done.

Syntax: "{" [field_name] ["!" conversion] [":" format_spec] "}"

# let's understand what each field means...
    field_name        ::=  arg_name ("." attribute_name | "[" element_index "]")*
    arg_name          ::=  [identifier | digit+]
    attribute_name    ::=  identifier
    element_index     ::=  digit+ | index_string
    index_string      ::=  <any source character except "]"> +
    conversion        ::=  "r" | "s" | "a"
    format_spec       ::=  [[fill]align][sign][#][0][width][grouping_option][.precision][type]

            # Looking at the underlying fields under format_spec...
            fill            ::=  <any character>
            align           ::=  "<" | ">" | "=" | "^"
            sign            ::=  "+" | "-" | " "
            width           ::=  digit+
            grouping_option ::=  "_" | ","
            precision       ::=  digit+
            type            ::=  "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%"

Refer https://docs.python.org/3/library/string.html#format-string-syntax

Kent Pawar
  • 1,978
  • 2
  • 24
  • 37
3

Simply

a = 10.1234
print(f"{a:.1f}")

Output: 10.1

a = 10.1234
print(f"{a:.2f}")

Output: 10.12

a = 10.1234
print(f"{a:.3f}")

Output: 10.123

a = 10.1234
print(f"{a:.4f}")

Output: 10.1234

Just change the value after the decimal point sign which represent how may decimal point you want to print.

2
a = 10.1234

print(f"{a:0.2f}")

in 0.2f:

  • 0 is telling python to put no limit on the total number of digits to display
  • .2 is saying that we want to take only 2 digits after decimal (the result will be same as a round() function)
  • f is telling that it's a float number. If you forget f then it will just print 1 less digit after the decimal. In this case, it will be only 1 digit after the decimal.

A detailed video on f-string for numbers https://youtu.be/RtKUsUTY6to?t=606

Rahul Sharma
  • 87
  • 1
  • 3
  • 1
    according to the docs https://docs.python.org/3/library/string.html#formatexamples `f` stands for "fixed point", not "floating notation" > Fixed-point notation. Displays the number as a fixed-point number. The default precision is 6. if you use `e` (seems to be the default), it will format your float in exponent notation. – linstantnoodles Jul 28 '20 at 13:11
  • Where did you get that the default precision is 6? – MrR Mar 07 '21 at 19:00
  • @MrR: It's said in the link he just wrote in the very same comment. – Bouncner Mar 07 '21 at 23:02
  • 1
    Ty, found it. For reference to someone as impaired as myself, search for "With no precision given, uses a precision of 6 digits after the decimal point for float" on that page for the 'f' "presentation type". – MrR Mar 08 '21 at 14:08
1

It seems that no one use dynamic formatter. To use dynamic formatter, use:

WIDTH = 7
PRECISION = 3
TYPE = "f"

v = 3
print(f"val = {v:{WIDTH}.{PRECISION}{TYPE}}")

Other format see: https://docs.python.org/3.6/library/string.html#format-specification-mini-language


Reference: Others SO Answer