Help finding problem in code

I am extremely new to Python and know just enough to write some very basic code. I am having trouble with the following code. The issue is that when I type some combinations of valid numbers in I get a correct answer and other times I get back my error message but I have triple checked and these numbers I have entered are valid. I can’t see where the fault in the code is, can anyone enlighten me on where I might be going wrong?

import numpy as np

def Cu10000ppm():
print(‘Cu: 10000ppm’)
print()
play = True

def Cu1000ppm():
print(‘Cu: 1000ppm’)
print()
play = True

def Cu800ppm():
print(‘Cu: 800ppm’)
print()
play = True

def Cu600ppm():
print(‘Cu: 600ppm’)
print()
play = True

def Cu300ppm():
print(‘Cu: 300ppm’)
print()
play = True

def Cu100ppm():
print(‘Cu: 100ppm’)
print()
play = True

def Cu50ppm():
print(‘Cu: 50ppm’)
print()
play = True

def Cu0ppm():
print (‘Cu: 0ppm’)
print()
play = True

def error():
print (‘Data error or out of range, please re-enter data’)
play = True

def error2():
print(‘That was not a number, please re-enter data’)
play = True

play = True
while play == True:
print(‘Enter Latitude’)
Lat = input()
print(‘Enter Logitude’)
Long = input()
print()

if Lat.isalpha() or Long.isalpha():
    error2()
else:
    Lat = float(Lat)
    Long = float(Long)

    if Lat in np.arange(27.4782, 27.4784, 0.0001) and Long in np.arange(153.0289, 153.0291, 0.0001):
        Cu10000ppm()
    elif Lat in np.arange(27.4779, 27.4784, 0.0001) and Long in np.arange(153.0287, 153.0292, 0.0001):
        Cu800ppm()                               
    elif Lat in np.arange(27.4775, 27.4785, 0.0001) and Long in np.arange(153.0283, 153.0294, 0.0001):
        Cu300ppm()
    elif Lat in np.arange(27.4769, 27.4786, 0.0001) and Long in np.arange(153.0278, 153.0295, 0.0001):
        Cu100ppm()
    elif Lat in np.arange(27.4762, 27.4789, 0.0001) and Long in np.arange(153.0273, 153.0299, 0.0001):
        Cu50ppm()
    else:
        error()

By Rhianen Dodd via Discussions on Python.org at 07Jun2022 01:55:

I am extremely new to Python and know just enough to write some very
basic code. I am having trouble with the following code. The issue is
that when I type some combinations of valid numbers in I get a correct
answer and other times I get back my error message but I have triple
checked and these numbers I have entered are valid. I can’t see where
the fault in the code is, can anyone enlighten me on where I might be
going wrong?

It would help to have examples of some numbers which success and some
which fail.

My suspicion is this code:

Lat = float(Lat)
Long = float(Long)
if Lat in np.arange(27.4782, 27.4784, 0.0001) and Long in np.arange(153.0289, 153.0291, 0.0001):

The arange function returns evenly spaced values from the first to the
second in steps of the third:
https://numpy.org/doc/stable/reference/generated/numpy.arange.html

So the above looks for Lat (for example) in the specific values
obtained by starting at 27.4782 and incrementing by 0.0001. If Lat
falls between any of those specific values the test will fail.

I would just write:

if 27.4782 <= Lat < 27.4784 and 153.0289 <= Long < 153.0291:

myself i.e. just test that the numbers fall in the desired fange, not
that the number falls on specific values between the two bounds.
Because it might not. It is like testing whether 5.5 is “in” the values
(5, 6, 7, 8) - it is in the range 5 through 8, but is not one of the
numbers you counted through.

The test is further complicated by the fact that even if you enter a
value like 27.4789 (exactly 7 * 0.0001 beyond the start) the test can
still fail. As it happens your ranges are very small (I hadn’t realised
this until I tried to demonstrate what I’m about to say), and this isn’t
obvious. But if we extend the range like this:

>>> list(np.arange(27.4782,27.5000,0.0001))
[27.4782, 27.4783, 27.4784, 27.4785, 27.4786, 27.4787, 27.4788, 
27.4789, 27.479, 27.4791, 27.4792, 27.4793, 27.4794, 
27.479499999999998, 27.479599999999998, 27.479699999999998, 
27.479799999999997, 27.479899999999997, 27.479999999999997, 
27.480099999999997, 27.480199999999996, 27.480299999999996, 
27.480399999999996, 27.480499999999996, 27.480599999999995, 
27.480699999999995, 27.480799999999995, 27.480899999999995, 
27.480999999999995, 27.481099999999994, 27.481199999999994, 
27.481299999999994, 27.481399999999994, 27.481499999999993, 
27.481599999999993, 27.481699999999993, 27.481799999999993, 
27.481899999999992, 27.481999999999992, 27.482099999999992, 
27.48219999999999, 27.48229999999999, 27.48239999999999, 
27.48249999999999, 27.48259999999999, 27.48269999999999, 
27.48279999999999, 27.48289999999999, 27.48299999999999, 
27.48309999999999, 27.48319999999999, 27.48329999999999, 
27.48339999999999, 27.48349999999999, 27.48359999999999, 
27.48369999999999, 27.483799999999988, 27.483899999999988, 
27.483999999999988, 27.484099999999987, 27.484199999999987, 
27.484299999999987, 27.484399999999987, 27.484499999999986, 
27.484599999999986, 27.484699999999986, 27.484799999999986, 
27.484899999999985, 27.484999999999985, 27.485099999999985, 
27.485199999999985, 27.485299999999985, 27.485399999999984, 
27.485499999999984, 27.485599999999984, 27.485699999999984, 
27.485799999999983, 27.485899999999983, 27.485999999999983, 
27.486099999999983, 27.486199999999982, 27.486299999999982, 
27.486399999999982, 27.48649999999998, 27.48659999999998, 
27.48669999999998, 27.48679999999998, 27.48689999999998, 
27.48699999999998, 27.48709999999998, 27.48719999999998, 
27.48729999999998, 27.48739999999998, 27.48749999999998, 
27.48759999999998, 27.48769999999998, 27.48779999999998, 
27.48789999999998, 27.48799999999998, 27.488099999999978, 
27.488199999999978, 27.488299999999978, 27.488399999999977, 
27.488499999999977, 27.488599999999977, 27.488699999999977, 
27.488799999999976, 27.488899999999976, 27.488999999999976, 
27.489099999999976, 27.489199999999975, 27.489299999999975, 
27.489399999999975, 27.489499999999975, 27.489599999999975, 
27.489699999999974, 27.489799999999974, 27.489899999999974, 
27.489999999999974, 27.490099999999973, 27.490199999999973, 
27.490299999999973, 27.490399999999973, 27.490499999999972, 
27.490599999999972, 27.490699999999972, 27.49079999999997, 
27.49089999999997, 27.49099999999997, 27.49109999999997, 
27.49119999999997, 27.49129999999997, 27.49139999999997, 
27.49149999999997, 27.49159999999997, 27.49169999999997, 
27.49179999999997, 27.49189999999997, 27.49199999999997, 
27.49209999999997, 27.49219999999997, 27.492299999999968, 
27.492399999999968, 27.492499999999968, 27.492599999999968, 
27.492699999999967, 27.492799999999967, 27.492899999999967, 
27.492999999999967, 27.493099999999966, 27.493199999999966, 
27.493299999999966, 27.493399999999966, 27.493499999999965, 
27.493599999999965, 27.493699999999965, 27.493799999999965, 
27.493899999999964, 27.493999999999964, 27.494099999999964, 
27.494199999999964, 27.494299999999964, 27.494399999999963, 
27.494499999999963, 27.494599999999963, 27.494699999999963, 
27.494799999999962, 27.494899999999962, 27.494999999999962, 
27.49509999999996, 27.49519999999996, 27.49529999999996, 
27.49539999999996, 27.49549999999996, 27.49559999999996, 
27.49569999999996, 27.49579999999996, 27.49589999999996, 
27.49599999999996, 27.49609999999996, 27.49619999999996, 
27.49629999999996, 27.49639999999996, 27.49649999999996, 
27.496599999999958, 27.496699999999958, 27.496799999999958, 
27.496899999999957, 27.496999999999957, 27.497099999999957, 
27.497199999999957, 27.497299999999957, 27.497399999999956, 
27.497499999999956, 27.497599999999956, 27.497699999999956, 
27.497799999999955, 27.497899999999955, 27.497999999999955, 
27.498099999999955, 27.498199999999954, 27.498299999999954, 
27.498399999999954, 27.498499999999954, 27.498599999999954, 
27.498699999999953, 27.498799999999953, 27.498899999999953, 
27.498999999999953, 27.499099999999952, 27.499199999999952, 
27.499299999999952, 27.49939999999995, 27.49949999999995, 
27.49959999999995, 27.49969999999995, 27.49979999999995, 
27.49989999999995]

you can see that the value start to not be expressed as 4 decimal
digits. This is because floating point number are not magic arbitrary
values but effectively a kind of scaled fraction, expressed that same
way we use scientific notation for large numbers. When we write
something like:

2.78e12

for the value 2780000000000, we mean 2.78 * 10^12. In this form, the
left value is the “mantissa”, which expresses the leading digits, and
the right value is the exponent, which expresses a scaling factor.

A Python floating point number uses this scheme internally, with a
mantissa and an exponent. This lets us express a value wide range of
values (becauseof the exponent. However, both the mantissa and exponent
are a fixed size, so effectively there are only so many digits of
precision available (governed by the size of the mantissa).

To make things worse, in a float these are done in base-2, instead of
base-10. Yet we write numbers in base-10 because that’s what we’ve been
taught since we were children. Why does this matter?

Because 0.0001 is 1/10000, or 1/(10^4) or 1/((2*5)^4) or 1/(2^4 * 5^4) to break that into its prime factors, and 5 is not a power of 2. As such, 0.0001 cannot be expressed perfectly with a float. Just very very closely.

And the consequence of that is that adding it to a value does not result
in perfectly round base-10 values, as you see in the list above.

For the first 10 or so values, the 4-decimal-points expression is the
closed thing to the internal value, but after that we need a heap of
further digits to get as close as possible to the internal number.

The consequence of that is that an equality test between floats is
almost never what you want to do, because the base-10 form is very often
just a very close approximation to the internal value.

When you write:

Lat in np.arange(27.4782, 27.4784, 0.0001)

you’re effectively asking for the values in that range, and doing an
exact equality test against the value in Lat. It will work here
because the range is small and things don’t get visibly fuzzy until
the range is larger, but in general it will not work.

But the short fix is to use the:

27.4782 <= Lat < 27.4784

version of the test. It doesn’t do an exact equality against specific
numbers, it does “is Lat between these two numbers?” instead.

Cheers,
Cameron Simpson cs@cskk.id.au

Thank you for your help Cameron, I think I just overthought this one a bit by the looks of it. I have changed my code using your fix with some slight tweaks and it works fantastically. I really appreciate your help.