616

I am getting a lot of decimals in the output of this code (Fahrenheit to Celsius converter).

My code currently looks like this:

def main():
    printC(formeln(typeHere()))

def typeHere():
    global Fahrenheit
    try:
        Fahrenheit = int(raw_input("Hi! Enter Fahrenheit value, and get it in Celsius!\n"))
    except ValueError:
        print "\nYour insertion was not a digit!"
        print "We've put your Fahrenheit value to 50!"
        Fahrenheit = 50
    return Fahrenheit

def formeln(c):
    Celsius = (Fahrenheit - 32.00) * 5.00/9.00
    return Celsius

def printC(answer):
    answer = str(answer)
    print "\nYour Celsius value is " + answer + " C.\n"



main()

So my question is, how do I make the program round every answer to the 2nd decimal place?

tomcounsell
  • 4,991
  • 3
  • 34
  • 34
Dolcens
  • 6,201
  • 2
  • 12
  • 12
  • 11
    A small remark regarding your code. There is no reason to have the Fahrenheit value kept as a global, it is enough (and better) to transmit it as a parameter to your functions. So, remove the "global Fahrenheit" line. In the formeln function, rename the parameter to the function "Fahreinheit" formeln(Fahreinheit). As for the rounding, you can just use the "%" parameters to display only the first 2 digits, and it should be rounded for these digits. There is no effect to the number of digits provided in the formula in formeln. – arieli Dec 08 '13 at 18:39

21 Answers21

1004

You can use the round function, which takes as its first argument the number and the second argument is the precision after the decimal point.

In your case, it would be:

answer = str(round(answer, 2))
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
rolisz
  • 10,794
  • 2
  • 19
  • 14
  • 56
    "[Note The behavior of `round()` for floats can be surprising: for example, `round(2.675, 2)` gives `2.67` instead of the expected `2.68`.](http://docs.python.org/2/library/functions.html#round)" – johnsyweb Dec 09 '13 at 00:56
  • 78
    I'm not sure what induced people to upvote the above comment. For the record, the fact that `round(2.675, 2)` gives `2.67` rather than `2.68` has nothing at all to do with Banker's rounding. – Mark Dickinson Mar 05 '18 at 18:28
  • 5
    **note**: this changes the value of answer. If you simply want to round for display, go with the answer of @Johnsyweb - https://stackoverflow.com/a/20457284/1498405 – hardmooth Mar 28 '18 at 07:35
  • 10
    @Johnsyweb I'm trying it today, year's after original post and it looks working as expected. Seems round() evolved over time. See below: round(1.379, 2) -> 1.38 round(1.372, 2) -> 1.37 round(1.375, 2) -> 1.38 – NightFurry Aug 16 '18 at 06:50
  • @NightFurry: That has not been my experience: https://ideone.com/UxO8E9 (Python (cpython 2.7.13)) and https://ideone.com/gCFGjg (Python 3 nbc (python 3.4)) – johnsyweb Aug 16 '18 at 09:14
  • `num = 1345000; round(num / 1000000, 2)` gives me 1.34 instead of 1.35, using python 3.6 – Jun Sep 12 '18 at 21:46
  • 4
    @NightFurry, you need to try `2.675`, not `1.375`. Still doesn't work with `Python 3.8.2`. – Det Mar 01 '20 at 22:42
  • 1
    WARNING ! on python3: `str(round(5.000, 2)) => 5.0` `str(round(5, 2)) => 5` – Zorro Mar 21 '21 at 00:46
  • 4
    round(2.675,2) gives 2.67, because 2.675 cannot be represented exactly by computer as the nature of float number. Run `from decimal import Decimal; Decimal.from_float(2.675)` , you can find 2.675 is actually stored as 2.67499999999999982236431605997495353221893310546875. I found [this link](https://docs.python.org/3/tutorial/floatingpoint.html#tut-fp-issues) is useful. – aruku7230 Apr 03 '21 at 09:33
  • To avoid surprises, `str.format()` is a decent way, I think – Pramit Aug 04 '22 at 20:21
205

Using str.format()'s syntax to display answer with two decimal places (without altering the underlying value of answer):

def printC(answer):
    print("\nYour Celsius value is {:0.2f}ºC.\n".format(answer))

Where:

  • : introduces the format spec
  • 0 enables sign-aware zero-padding for numeric types
  • .2 sets the precision to 2
  • f displays the number as a fixed-point number
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
johnsyweb
  • 136,902
  • 23
  • 188
  • 247
  • 4
    This is the most useful answer IMO - keeps the actual value intact and is simple to implement! Thanks! – BrettJ Dec 30 '17 at 00:08
  • Not sure why, but '{:0.2f}'.format(0.5357706) gives me '0.54' (python 3.6) – Noam Peled Apr 02 '18 at 02:00
  • 5
    @NoamPeled: Why shouldn't it? `0.5357...` is closer to `0.54` than to `0.53`, so rounding to `0.54` makes sense. – ShadowRanger Nov 19 '19 at 18:20
  • `"{:0.2f}".format(1.755)` -> 1.75 `"{:0.2f}".format(1.7551)` -> 1.76 - However, I would have both expected to equal 1.76. – Janothan Mar 05 '20 at 13:59
  • (Python Version: 3.6.10) – Janothan Mar 05 '20 at 14:13
  • 1
    @Janothan floating point values are not precise. Try `"{:0.20f}".format(1.755)` and you'll see why the value with two decimal places is displayed as `1.75`. – Matthias Apr 17 '20 at 21:58
  • 1
    What does the sign-aware zero-padding here mean? I get that it'll be padded with leading zeros if the number is not long enough, but since there are no minimum length requirements here (like `{:05.2f}`), what does the zero do? – Jack Jul 23 '20 at 19:03
  • 3
    @jackz314 6.5 years (and many Python versions) after I wrote this answer, I forget why I thought the zero to be worth including. – johnsyweb Jul 25 '20 at 06:44
88

Most answers suggested round or format. round sometimes rounds up, and in my case I needed the value of my variable to be rounded down and not just displayed as such.

round(2.357, 2)  # -> 2.36

I found the answer here: How do I round a floating point number up to a certain decimal place?

import math
v = 2.357
print(math.ceil(v*100)/100)  # -> 2.36
print(math.floor(v*100)/100)  # -> 2.35

or:

from math import floor, ceil

def roundDown(n, d=8):
    d = int('1' + ('0' * d))
    return floor(n * d) / d

def roundUp(n, d=8):
    d = int('1' + ('0' * d))
    return ceil(n * d) / d
s4w3d0ff
  • 1,091
  • 10
  • 24
  • 2
    "values are rounded to the closest multiple of 10 to the power minus ndigits;" https://docs.python.org/3/library/functions.html#round so no, round does not always round up, e.g. `round(2.354, 2) # -> 2.35` – Pete Kirkham Jan 13 '18 at 23:32
  • @PeteKirkham you are right, I edited my answer to make more sense and accurate. – s4w3d0ff Jan 19 '18 at 16:48
  • Well, you should check your solution with negative values... math.floor(0.5357706*100)/100 -> 0.53 math.floor(-0.5357706*100)/100 -> -0.54 – Noam Peled Apr 02 '18 at 02:06
  • 3
    -0.54 is the correct answer for rounding -0.5357706 down because it is a negative number, -0.54 < -0.53 – s4w3d0ff Apr 10 '18 at 16:53
  • 6
    I would use `10**d` instead of `int('1' + ('0' * d))`. – Jonathon Reinhart Mar 29 '19 at 01:49
65

If you just want to print the rounded result out, you can use the f-strings introduced since Python 3.6. The syntax is the same as str.format()'s format string syntax, except you put a f in front of the literal string, and you put the variables directly in the string, within the curly braces.

.2f indicates rounding to two decimal places:

number = 3.1415926
print(f"The number rounded to two decimal places is {number:.2f}")

Output:

The number rounded to two decimal places is 3.14
Jack
  • 5,354
  • 2
  • 29
  • 54
  • 1
    This will round 39.555 to 39.55, which gives incorrect results if you expect the rounding to be 39.56 – martin36 Nov 19 '20 at 19:35
  • 2
    If anyone does not place the `f` after `.2`, a number like `14.426599999999999` will round to `1.4e+01`. As far as Python 3.8.6 – carloswm85 Jun 28 '21 at 21:35
  • 1
    @martin36, this is not an incorrect result, since 39.555 cannot be represented exactly in floating-point format, so Python will actually store the number 39.554999999999999...., which is correctly rounded to 39.55. If someone expects it to be rounded to 39.56, then the expectations are wrong IMHO. When working with floating-point numbers, you should be aware of these "inaccuracies", and either accept them or choose a different data type. – wovano Dec 28 '22 at 16:31
63

You can use the round function.

round(80.23456, 3)

will give you an answer of 80.234

In your case, use

answer = str(round(answer, 2))
Dharman
  • 30,962
  • 25
  • 85
  • 135
Satyaki Sanyal
  • 1,201
  • 11
  • 12
21

You want to round your answer.

round(value,significantDigit) is the ordinary solution to do this, however this sometimes does not operate as one would expect from a math perspective when the digit immediately inferior (to the left of) the digit you're rounding to has a 5.

Here's some examples of this unpredictable behavior:

>>> round(1.0005,3)
1.0
>>> round(2.0005,3)
2.001
>>> round(3.0005,3)
3.001
>>> round(4.0005,3)
4.0
>>> round(1.005,2)
1.0
>>> round(5.005,2)
5.0
>>> round(6.005,2)
6.0
>>> round(7.005,2)
7.0
>>> round(3.005,2)
3.0
>>> round(8.005,2)
8.01

Assuming your intent is to do the traditional rounding for statistics in the sciences, this is a handy wrapper to get the round function working as expected needing to import extra stuff like Decimal.

>>> round(0.075,2)

0.07

>>> round(0.075+10**(-2*6),2)

0.08

Aha! So based on this we can make a function...

def roundTraditional(val,digits):
   return round(val+10**(-len(str(val))-1), digits)

Basically this adds a really small value to the string to force it to round up properly on the unpredictable instances where it doesn't ordinarily with the round function when you expect it to. A convenient value to add is 1e-X where X is the length of the number string you're trying to use round on plus 1.

The approach of using 10**(-len(val)-1) was deliberate, as it the largest small number you can add to force the shift, while also ensuring that the value you add never changes the rounding even if the decimal . is missing. I could use just 10**(-len(val)) with a condiditional if (val>1) to subtract 1 more... but it's simpler to just always subtract the 1 as that won't change much the applicable range of decimal numbers this workaround can properly handle. This approach will fail if your values reaches the limits of the type, this will fail, but for nearly the entire range of valid decimal values it should work.

So the finished code will be something like:

def main():
    printC(formeln(typeHere()))

def roundTraditional(val,digits):
    return round(val+10**(-len(str(val))-1))

def typeHere():
    global Fahrenheit
    try:
        Fahrenheit = int(raw_input("Hi! Enter Fahrenheit value, and get it in Celsius!\n"))
    except ValueError:
        print "\nYour insertion was not a digit!"
        print "We've put your Fahrenheit value to 50!"
        Fahrenheit = 50
    return Fahrenheit

def formeln(c):
    Celsius = (Fahrenheit - 32.00) * 5.00/9.00
    return Celsius

def printC(answer):
    answer = str(roundTraditional(answer,2))
    print "\nYour Celsius value is " + answer + " C.\n"

main()

...should give you the results you expect.

You can also use the decimal library to accomplish this, but the wrapper I propose is simpler and may be preferred in some cases.


Edit: Thanks Blckknght for pointing out that the 5 fringe case occurs only for certain values here.

Wyetro
  • 8,439
  • 9
  • 46
  • 64
Jason R. Mick
  • 5,177
  • 4
  • 40
  • 69
  • This doesn't work for negative numbers e.g -4.625 evaluates to -4.62. Can you modify it to work for negative numbers? – JasonX Oct 01 '22 at 13:47
21

If you need avoid floating point problem on rounding numbers for accounting, you can use numpy round.

You need install numpy :

pip install numpy

and the code :

import numpy as np

print(round(2.675, 2))
print(float(np.round(2.675, 2)))

prints

2.67
2.68

You should use that if you manage money with legal rounding.

Samuel Dauzon
  • 10,744
  • 13
  • 61
  • 94
  • This does not work if the last digit is a 0. For example the number 39.90 will be rounded to 39.9 – martin36 Nov 19 '20 at 13:15
  • 1
    This method gives you a decimal value not a string. You should use @jackz314 if you want a string with the format you want – Samuel Dauzon Nov 19 '20 at 14:54
  • if running on pi, use the pi version: apt install python3-numpy – Shawn Sep 23 '21 at 17:06
  • This doesn't work. `np.round(2.665, 2)` returns `2.66` while `round(2.665, 2)` returns `2.67`. Here is my solution. https://stackoverflow.com/a/53329223/6069907 – discover Nov 09 '21 at 21:02
  • @SamuelDauzon Of course I tried it on my local. I got my result on python 3.7(win10) and numpy 1.19.3. – discover Nov 10 '21 at 06:37
13
float(str(round(answer, 2)))
float(str(round(0.0556781255, 2)))
Matthew Verstraete
  • 6,335
  • 22
  • 67
  • 123
Mahadi
  • 131
  • 1
  • 2
10

If you need not only round result but elso do math operations with round result, then you can use decimal.Decimal https://docs.python.org/2/library/decimal.html

from decimal import Decimal, ROUND_DOWN

Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32') 
Ryabchenko Alexander
  • 10,057
  • 7
  • 56
  • 88
10
from decimal import Decimal, ROUND_HALF_UP

# Here are all your options for rounding:
# This one offers the most out of the box control
# ROUND_05UP       ROUND_DOWN       ROUND_HALF_DOWN  ROUND_HALF_UP
# ROUND_CEILING    ROUND_FLOOR      ROUND_HALF_EVEN  ROUND_UP

our_value = Decimal(16.0/7)
output = Decimal(our_value.quantize(Decimal('.01'), 
rounding=ROUND_HALF_UP))
print output
Roman
  • 2,464
  • 2
  • 17
  • 21
9

Just use the formatting with %.2f which gives you rounding down to 2 decimals.

def printC(answer):
    print "\nYour Celsius value is %.2f C.\n" % answer
Santosh Ghimire
  • 3,087
  • 8
  • 35
  • 63
9

You can use round operator for up to 2 decimal

num = round(343.5544, 2)
print(num) // output is 343.55
Asad Manzoor
  • 1,355
  • 15
  • 18
5

You can use the string formatting operator of python "%". "%.2f" means 2 digits after the decimal point.

def typeHere():
    try:
        Fahrenheit = int(raw_input("Hi! Enter Fahrenheit value, and get it in Celsius!\n"))
    except ValueError:
        print "\nYour insertion was not a digit!"
        print "We've put your Fahrenheit value to 50!"
        Fahrenheit = 50
    return Fahrenheit

def formeln(Fahrenheit):
    Celsius = (Fahrenheit - 32.0) * 5.0/9.0
    return Celsius

def printC(answer):
    print "\nYour Celsius value is %.2f C.\n" % answer

def main():
    printC(formeln(typeHere()))

main()

http://docs.python.org/2/library/stdtypes.html#string-formatting

arieli
  • 149
  • 3
5

To avoid surprising value from round() this is my approche:

Round = lambda x, n: eval('"%.'+str(int(n))+'f" % '+repr(int(x)+round(float('.'+str(float(x)).split('.')[1]),n)))

print(Round(2, 2))       # 2.00
print(Round(2.675, 2))   # 2.68
George
  • 6,886
  • 3
  • 44
  • 56
Zorro
  • 1,085
  • 12
  • 19
3

Truncating to 2 digitis:

somefloat = 2.23134133
truncated = int( somefloat * 100 ) / 100  # 2.23
Evandro Coan
  • 8,560
  • 11
  • 83
  • 144
2

Here is an example that I used:

def volume(self):
    return round(pi * self.radius ** 2 * self.height, 2)

def surface_area(self):
    return round((2 * pi * self.radius * self.height) + (2 * pi * self.radius ** 2), 2)
1
round(12.3956 - 0.005, 2)  # minus 0.005, then round.

The answer is from: https://stackoverflow.com/a/29651462/8025086

buxizhizhoum
  • 1,719
  • 1
  • 23
  • 32
1

The easiest solution I found so far, dunno why people ain't using it.

# Make sure the number is a float
a = 2324.55555
# Round it according to your needs
# dPoints is the decimals after the point
dPoints = 2
# this will round the float to 2 digits
a = a.__round__(dPoints)
if len(str(a).split(".")[1]) < dPoints:
    # But it will only keep one 0 if there is nothing,
    # So we add the extra 0s we need
    print(str(a)+("0"*(dPoints-1)))
else:
    print(a)
1

Simple example

bill = 10.24 print(round(10.241))

Savana Rohit
  • 50
  • 4
  • 12
  • 2
    Hi @Savana Rohit, this answer is a duplicate of other answers here. Thank you for contributing! There's nothing wrong with your answer, but others have already supplied this answer. I'm recommending deletion of this answer. – TempleGuard527 Aug 03 '22 at 16:03
0

As you want your answer in decimal number so you dont need to typecast your answer variable to str in printC() function.

and then use printf-style String Formatting

codiacTushki
  • 750
  • 1
  • 9
  • 22
0

Not sure why, but '{:0.2f}'.format(0.5357706) gives me '0.54'. The only solution that works for me (python 3.6) is the following:

def ceil_floor(x):
    import math
    return math.ceil(x) if x < 0 else math.floor(x)

def round_n_digits(x, n):
    import math
    return ceil_floor(x * math.pow(10, n)) / math.pow(10, n)

round_n_digits(-0.5357706, 2) -> -0.53 
round_n_digits(0.5357706, 2) -> 0.53
Noam Peled
  • 4,484
  • 5
  • 43
  • 48