How to Have an Algorithm Round in a "Smart" Way Automatically

I would like to round number in a code but in a way that it adapts to each values.

For example i would like a rounding algorithm to return :

  • 0.999999 it should return 1
  • 0.0749999 it should return 0.075
  • 0.006599 it should return 0.0066 and so on ...

I don't know in advance the number of digits (which is kinda my problem)

I was thinking to use strings to find where are the 9s (or count the 0s) but it is quite a lot of effort for that i was thinking ?

If you know any way to do that (if possible without advanced libraries) i would appreciate.

Thanks.

6

3 Answers

It's some complicated. but, It works. Please make sure the result is what you want. I think you can understand how to round the number from code.

def clear9(numstr):
    liststr = list(numstr)
    for index in range(len(liststr)-1,-1,-1):
        if liststr[index] == '.': continue
        if liststr[index] == '9': 
            liststr[index] = '0'
            if index == 0:
                liststr.insert(0, '1')
        else: 
            if index != len(liststr)-1:
                liststr[index] = str(int(liststr[index])+1)
            break
    numstr = ''
    for item in liststr:
        numstr += item
    return numstr

def myround(num):
    numstr = str(num)
    numstr = clear9(numstr)
    return float(numstr)


print (myround(9.05))
print (myround(9.999999))
print (myround(0.999999))
print (myround(0.0749999))
print (myround(0.006599))
print (myround(0.00659923))
print (myround(0.09659923))
print (myround(-0.00659923))
9.05
10.0
1.0
0.075
0.0066
0.00659923
0.09659923
-0.00659923
4
import math

def round_(number):
    dist = int(math.log10(abs(number))) #number of zeros after decimal point
    return (round(number, abs(dist) + 2) if dist != 0 else round(number))

print(round_(0.999999))
print(round_(0.0749999))
print(round_(0.006599))
print(round_(-0.00043565))

output:

1
0.075
0.0066
-0.00044
4

Dealing with floating point numbers is tricky. You want to do a kind of round-off in base 10, but floating point numbers are base 2.

So I propose to use the decimal module, which can represent real numbers exactly, as opposed to base-2 floating point.:

from decimal import Decimal

def myround(num):
    dec = Decimal(num)
    adj = abs(dec.adjusted())+1
    return round(num, adj)

Look at the documentation for Decimal.adjusted() to understand how this works.

A test:

In [1]: from decimal import Decimal                                                                      

In [2]: def myround(num): 
   ...:     dec = Decimal(num) 
   ...:     adj = abs(dec.adjusted())+1 
   ...:     return round(num, adj) 
   ...:                                                                                                  

In [3]: myround(0.999999)                                                                                
Out[3]: 1.0

In [4]: myround(0.006599)                                                                                
Out[4]: 0.0066

In [5]: myround(0.0749999)                                                                               
Out[5]: 0.075
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Sarah Jenkins

Sarah Jenkins

Senior Technology Editor & AI Specialist

Sarah Jenkins is a veteran tech journalist with over 12 years of experience covering artificial intelligence, mobile innovations, and digital ethics. Her insights have appeared in leading technology publications worldwide.

Share this article
Twitter Facebook Pinterest