5

Currently I am trying to solve a problem, where I am supposed to print the answer upto two decimal points without rounding off. I have used the below code for this purpose

import math
a=1.175                            #value of a after some division
print(math.floor(a*100)/100)

The output we get is:

1.17                              #Notice value which has two decimal points & not rounded

But the real problem starts when I try to print a number which is evenly divisible, after the decimal point only one zero is displayed. I have used the same code as above, but now

a=25/5                                   #Now a is perfectly divisible
print(math.floor(a*100)/100)

The output displayed now is

5.0                                      #Notice only one decimal place is printed

what must be done rectify this bug?

hc_dev
  • 8,389
  • 1
  • 26
  • 38
DrinkandDerive
  • 67
  • 1
  • 1
  • 7

2 Answers2

11

The division works and returns adequate precision in result.

So your problem is just about visualization or exactly:

  • string-representation of floating-point numbers

Formatting a decimal

You can use string-formatting for that. For example in Python 3, use f-strings:

twoFractionDigits = f"{result:.2f}"

or print(f"{result:.2f}")

The trick does .2f, a string formatting literal or format specifier that represents a floating-point number (f) with two fractional digits after decimal-point (.2).

See also:

Try on the Python-shell:

Python 3.6.9 (default, Dec  8 2021, 21:08:43) 
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> a=1.175                            #value of a after some division
>>> result = math.floor(a*100)/100
>>> result
1.17
>>> print(result)
1.17
>>> a=25/5                                   #Now a is perfectly divisible
>>> result = math.floor(a*100)/100
>>> result
5.0
>>> print(result)
5.0
>>> print(f"{result:.2f}")
5.00

Formatting a decimal as percentage

Similar you can represent the ratio as percentage: print(f"{result:.2f} %")

prints:

5.00 %

A formatting shortcut for percentage can be: print(f"{25/100:.2%}") Which converts the result of 25/100 == 0.25 to:

25.00%

Note: The formatting-literal .2% automatically converts from ratio to percentage with 2 digits after the decimal-point and adds the percent-symbol.

Formatting a decimal with specific scale (rounded or truncated ?)

Now the part without rounding-off, just truncation. As example we can use the repeating decimal, e.g. 1/6 which needs to be either rounded or truncated (cut-off) after a fixed number of fractional digits - the scale (in contrast to precision).

>>> print(f"{1/6:.2}")
0.17
>>> print(f"{1/6:.2%}")
16.67%

Note how the formatted string is not truncated (to 0.16) but rounded (to 0.17). Here the scale was specified inside formatting-literal as 2 (after the dot).

See also:

Formatting many decimals in fixed width (leading spaces)

Another example is to print multiple decimals, like in a column as right-aligned, so you can easily compare them.

Then use string-formatting literal 6.2f to add leading spaces (here a fixed-width of 6):

>>> print(f"{result:6.2f}")
  5.00
>>> print(f"{100/25*100:6.2f}")
400.00
>>> print(f"{25/100*100:6.2f}")
 25.00

See also

All the formatting-literals demonstrated here can also be applied using

  • old-style %-formatting (also known as "Modulo string formatting") which was inherited from printf method of C language. Benefit: This way is also compatible with Python before 3.6).
  • new-style .format method on strings (introduced with Python 3)

See theherk's answer which demonstrates those alternatives.

Learn more about string-formatting in Python:

hc_dev
  • 8,389
  • 1
  • 26
  • 38
  • 1
    @theherk, your answer is great and shows also __common issues with floating-points__. I focused on string-formatting in general using "For example" f-string's as a useful pattern. – hc_dev Jan 27 '22 at 17:30
  • 1
    I regretted saying anything. This is a comprehensive answer, and the important thing here is that good questions get good answers. You're out here doing the lord's work, posting answers, adding tags, editing what needs edited. :) – theherk Jan 27 '22 at 17:43
2

You can find this recommendation in the official Python tutorial: 15. Floating Point Arithmetic: Issues and Limitations.

For more pleasant output, you may wish to use string formatting to produce a limited number of significant digits

print("%.2f" % 3.0)
3.00

or

format(3.0, ".2f")
'3.00'
theherk
  • 6,954
  • 3
  • 27
  • 52
  • A bit off-topic but curious to learn from you: What are the benefits for referencing URLs as foot-notes like `[1]` to be listed at the end ? Is it re-usability (multiple cross-references can point to a single URL) ? – hc_dev Jan 27 '22 at 17:33
  • 1
    It is for 2 reasons, neither of which are important. You correctly point out one, as the same reference can be used many times. The other is that, no matter the length of the url, the readability of the document in markdown format is not hindered. – theherk Jan 27 '22 at 17:42
  • Wow thanks, that is __link formatting best-practice__ that needs to be shared ️ (if not here, then in SO-meta or [Help: Formatting](https://stackoverflow.com/help/formatting), section "Links") – hc_dev Jan 27 '22 at 17:53
  • What % sign means in ```print("%.2f" % 3.0)``` line? – michal roesler Oct 17 '22 at 14:50
  • 1
    @michalroesler: It is the character that indicates a replacement in [string interpolation](https://docs.python.org/3/tutorial/inputoutput.html#old-string-formatting) (old-style). – theherk Oct 18 '22 at 06:26