1

I am new to coding and would like to round a list of float values to the same decimal place based upon a float value in the list that has the most decimal places. For example, say my_list = [23.40, 12.45, 54.21]. How can I go about printing the values such that the zero at the end of 23.40 is printed out as well? In my example, I know that you could round to 2 decimal places, but what if that were not the case (ex. my_list = [23.40, 12.4523, 87.123])?

Sincerely, Nova

leangaurav
  • 393
  • 2
  • 11
low_on_HP
  • 11
  • 2
  • Convert each float to str to find out the number of decimal places it has, find the maximum of them, print floats out formatted with this number of digits. With which step do you have problems? – Michael Butscher Oct 14 '21 at 03:37

3 Answers3

3

This is related to formatting float values to a string with given precision. Below is a step-by-step example on how to print all list values with the maximum decimal precision.

my_list = [23.40, 12.4523, 87.123]

# generate a string repr
my_list_str = [str(x) for x in my_list]

# find the max num of decimal places
max_decimal = max([ len(x) - x.find('.') - 1 for x in my_list_str])
print("max_decimal", max_decimal)

# generate a format string
fmt_str = f"%0.{max_decimal}f"
print("fmt_str", fmt_str)

# format all numbers to same decimal places
my_list_str = [fmt_str % x for x in my_list]
print("my_list_str", my_list_str)

# join all strings
res = "[" + ", ".join(my_list_str) + "]"
print(res)

Output

max_decimal 4
fmt_str %0.4f
my_list_str ['23.4000', '12.4523', '87.1230']
[23.4000, 12.4523, 87.1230]

The code can be reduced to lesser lines using higher order functions and more list comprehensions, but the example should give a general idea on the steps.

leangaurav
  • 393
  • 2
  • 11
  • The number of decimal places in the output numbers is 5. However the maximum number of decimal places in the input numbers is 4. – Xukrao Oct 14 '21 at 04:14
  • @leangaurav, not to take away from your answer as I quite like your approach, but this line spits out an error for me in Python 3.8.8: `my_list_str = [fmt_str % x for x in my_list]`. Specifically, `ValueError: incomplete format`. I have never generated a variable like fmt_str so not sure how to suggest a fix. – ramzeek Oct 14 '21 at 04:20
  • @xukrao, thanks for the edit, I missed the -1 there. @wikikikitiki, thanks for pointing that as well, the `f` in format specifier got deleted. Fixed that. – leangaurav Oct 14 '21 at 04:25
1

The first step is to find the maximum precision of your list of points. To do that, you need a way to find the precision of a number. Here is a function call that can do that (but see note at bottom of post):

def decimal_precision(x):
    if isinstance(x, int): # if x is an integer there are no decimals
        return(0)
    # if it is a float count the number of values after the decimal
    x_str = str(x)    # start by converting x to a string
    x_split = x_str.split('.') # the split command creates a list, dividing the string at '.'
    n_decimals = len(x_split[1]) # the length of element 1 of x_split will be the number of decimals
    return(n_decimals)

Now we need to see which entry in your list has the most decimals

my_list = [23.40, 12.4523, 87.123]

max_precision = 0
for entry in my_list:
    prec = decimal_precision(entry)

    if prec > max_precision:
        max_precision = prec

Finally, printing the values:

for entry in my_list:
    print(f'{entry:.{max_precision}f}') 
# 23.4000
# 12.4523
# 87.1230

NOTE: This can actually be a trickier question to answer than at first glance because of how floating point arithmetic works. See for example, this post. That post is about a decade old, though, and current versions of Python (I'm using 3.8.8) seem to do something to try to improve this under the hood. Above, I assumed to use a simpler approach for estimating precision than the one suggested in the accepted answer for the post referenced above. If you ran into issues due to floating point arithmetic, you'd might want to consider a more elaborate function.

ramzeek
  • 2,226
  • 12
  • 23
  • Kudos to the other posters for much more succinct answers than mine. You mentioned you were new to coding so to explain things a bit more in depth, I expanded a bit more than how I would have normally coded it. Hopefully my more drawn out explanation helps you understand their code, which is more elegant. – ramzeek Oct 14 '21 at 04:29
0

This problem can be solved using two list comprehensions: one list comprehensions to determine the number of decimal places, and one list comprehension to construct strings containing the numbers.

my_list = [23.40, 12.4523, 87.123]

dec = [len(str(elem).split(".")[1]) for elem in my_list]
str_list = [f'{elem:.{max(dec)}f}' for elem in my_list]

print(str_list)
# Output:
# ['23.4000', '12.4523', '87.1230']
Xukrao
  • 8,003
  • 5
  • 26
  • 52