Disgusting
Disgusting

Reputation: 123

Python3 Decimal Point Precision

I am writing a graphing calculator in Python 3

However, this code here is giving me problems.

def domainGen(start,end,step):
    #generates a list of points for t, x, or theta to be equal to.
    #Acts like a floating point equivalent to "range" except it generates a whole list object, not just an iterator
    domain = [] #creates an empty list to store the domain
    minInt = start//step #rounding towards zero
    maxInt = end//step #rounding towards zero
    for n in range(minInt-1,maxInt + 1):
        if n*step >= start and n*step <= end:domain.append(n*step)
    return domain

The variables of this function are all user inputs and need to be floats or Decimal() values to allow for arbitrary precision.

However, when running this code I get a large number of floating point calculation errors, seemingly at random, to the numbers in the list "domain".

This is the output for domainGen(0,10,0.1):

[0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7000000000000001, 0.8, 0.9, 1.0, 1.1, 1.2000000000000002, 1.3, 1.4000000000000001, 1.5, 1.6, 1.7000000000000002, 1.8, 1.9000000000000001, 2.0, 2.1, 2.2, 2.3000000000000003, 2.4000000000000004, 2.5, 2.6, 2.7, 2.8000000000000003, 2.9000000000000004, 3.0, 3.1, 3.2, 3.3000000000000003, 3.4000000000000004, 3.5, 3.6, 3.7, 3.8000000000000003, 3.9000000000000004, 4.0, 4.1000000000000005, 4.2, 4.3, 4.4, 4.5, 4.6000000000000005, 4.7, 4.800000000000001, 4.9, 5.0, 5.1000000000000005, 5.2, 5.300000000000001, 5.4, 5.5, 5.6000000000000005, 5.7, 5.800000000000001, 5.9, 6.0, 6.1000000000000005, 6.2, 6.300000000000001, 6.4, 6.5, 6.6000000000000005, 6.7, 6.800000000000001, 6.9, 7.0, 7.1000000000000005, 7.2, 7.300000000000001, 7.4, 7.5, 7.6000000000000005, 7.7, 7.800000000000001, 7.9, 8.0, 8.1, 8.200000000000001, 8.3, 8.4, 8.5, 8.6, 8.700000000000001, 8.8, 8.9, 9.0, 9.1, 9.200000000000001, 9.3, 9.4, 9.5, 9.600000000000001, 9.700000000000001, 9.8, 9.9]

I would like a function that can tell me the number of decimal places a user has specified their values to so that I can then round these numbers off to the same precision.

Is there a built in function that can help me?

If not, what is the most Pythonic way to solve this issue?

Notes:

I am aware there are perfectly good graph modules out there and want to do this myself as an exercise.

I have heard of the module "Decimal" but am not sure exactly how to use it and if it would help in this context.

Decimal Point precision is preferred but a decent workaround with Significant Figure precision could maybe be useful.

I am aware of this question but I understand why floating point errors occur, as I say, I need a function that tells me how many decimal points of precision a user has given me, so its not a duplicate.

Upvotes: 0

Views: 205

Answers (1)

John Coleman
John Coleman

Reputation: 52008

If someone enters a float or int literal you could do something like this to it:

def get_float(s):
    if '.' in s:
        return float(s), len(s) - s.index('.') - 1
    else:
        return float(s), 0

This function returns a tuple consisting of the corresponding float and the number of characters after the decimal point. It would need to be modified if you want to properly handle float literals which include e or E.

For example:

>>> get_float('2')
(2.0, 0)
>>> get_float('2.1')
(2.1, 1)
>>> get_float('.001')
(0.001, 3)
>>> get_float('-0.001')
(-0.001, 3)

As a practical problem, is it really safe to assume that a user really just cares about 2 decimal places of accuracy because they entered '2.01' rather than '2.01000'? If you want to have a user-specified precision, why not have the user explicitly provide that precision?

Upvotes: 1

Related Questions