Hefe
Hefe

Reputation: 439

How to extend number of decimals that show

I have this code that I need to change to pass the below assert test:

def degrees_to_dms(degrees_fraction):
    ''' Convert degrees to degree, minute, second 3-tuples'''
    degrees = int(degrees_fraction)
    minutes = abs(degrees_fraction - degrees) * 60.0
    seconds = np.round((degrees_fraction - degrees - minutes/60.0) * 3600.0, 2)
    return (degrees, abs(minutes), abs(seconds))


def dms_to_degrees(d,m,s):
    ''' Convert degrees, minutes, seconds to fractional degrees'''
    return float(d)+float(m/60.00)+float(s/3600.00)

And it needs to pass this assert test:

assert dms_to_degrees(*degrees_to_dms(42.2833333333)) == 42.28333333333333

The only difference is that there are four more 3's in the expected outcome. In iterating through each step of the process, it looks like the addition of float(d) with float(m/60.00) in dms_to_degrees leads to a rounding of the decimal places. I'd like to make it so that it outputs those extra 3's. I also noticed that m/60 = 0.2833333332999999, so I don't know why they expect the 2999999 to become all 3's anyways. But maybe there is a different approach needed altogether.

Thank you.

Upvotes: 1

Views: 134

Answers (1)

Stef
Stef

Reputation: 30629

This is not an issue of numbers of decimals shown in the output but a normal floating point issue.

You can show more decimals in the output by formatting:

print(f'{dms_to_degrees(*degrees_to_dms(42.2833333333)):.50f}')
# 42.28333333329999987881819834001362323760986328125000

Comparison of floating point numbers is pointless and not portable. You should use isclose for comparing floats:

assert np.isclose(dms_to_degrees(*degrees_to_dms(42.2833333333)) , 42.28333333333333)

Update If you can't change the test you can fix degrees_to_dms by rounding the minutes to a whole number if the value is very close to an integer (smaller then some epsilon of say 1e-6):

def degrees_to_dms(degrees_fraction):
    ''' Convert degrees to degree, minute, second 3-tuples'''
    degrees = int(degrees_fraction)
    minutes = abs(degrees_fraction - degrees) * 60.0
    if (abs(minutes - round(minutes)) < 1e-6):
        minutes = round(minutes)
    seconds = np.round((degrees_fraction - degrees - minutes/60.0) * 3600.0, 2)
    return (degrees, abs(minutes), abs(seconds))

In my opinion, however, this is just a trick to make an ill-designed test case pass. See for instance the output of 42.2833333333 at https://www.fcc.gov/media/radio/dms-decimal: they show 42° 16' 59.9982" instead of 42° 17' 0.0".

Upvotes: 2

Related Questions