Computer guesses the user's number
General logic and flow

I recommend removing not x and instead just originally setting x = LOW_NO-1 for your while

x = LOW_NO - 1
while HIGH_NO &lt; x or x &lt; LOW_NO:


Next, I recommend you just keep the while loop instead of recursively calling getno if the user enters and invalid int. You could just use pass to tell the loop to skip onto the next loop. The old value of x will be preserved so you the condition is still true. Though I do recommend informing the user why their input was rejected.

try:
    x = int(x)
except ValueError:
    print ("That's not a valid number")


Lastly, just return x, no need for brackets.

In your approxhalf, there's no need for abs. Your LOW_NO and HIGH_NO values should prevent wildly off numbers, and if you ever want to use negative numbers there's no need to prevent it like this. I do recommend using int() here just so that it prints without decimal places, since the actual result is based on whole numbers. You also don't need to assign x just to return it. Return the value directly.

def approxhalf(lowno, highno):
    # Find integer approx halfway point between two values.
    return int(round((lowno+highno)/2))


The reason rounding has confused you is probably to do with how floats work. For example 0.1 is actually 0.1000000000000000055511151231257827021181583404541015625. This can affect rounding in cases where you think a number is x.5 but it's actually represented in memory as x.49942342341, leading to a number that rounds down instead of up.

In your checking system, I think you should rearrange the flow.

It's confusing to check if compguess is right and at the same time check if it's more than 2 off. You should do each distinct condition as it comes, my preference is to start with the correct answer and broaden out from there:

if compguess == userno:
    print('%s. I guess %s' % (count, compguess))
    print("Got it!")
    break 


A note, you used while compguess != userno. But you break out of the loop for other conditions later down. I'd recommend instead using while True and then use break for the various points you actually want the loop to be over.

if abs(no2-no1) &lt;= 2:
    # For when the low and high numbers are consecutive
    if no1 == userno:
        print('%s. I guess %s' % (count, no1))
        print("Got it")
    elif no2 == userno:
        print('%s. I guess %s' % (count, no2))
        print("Got it")
    else:
        print("ERROR: Neither %s nor %s == %s" % (no1, no2, userno))
    break


About that last else. If you're going to have a condition for a seemingly impossible situation, then you should at least output some relevant data to understand what went wrong. Also I put the break outside the if branches because it should break regardless of which condition is True. Note that now we don't need an if for the next part, we know it has to evaluate since no other condition (which would end the loop) was True.

if compguess &gt; userno:
    no2 = compguess
elif compguess &lt; userno:
    no1 = compguess


Style advice

Reading PEP0008 will tell you all about what I'm saying here and more. It's highly recommended reading.

You should name your functions using underscores, as that's the recommendation. So you'd have get_no(), guess_no() and approx_half(). As for variable names, CamelCase is better for compGuess and userNo.

You almost but not quite have docstrings. You have comments explaining what each function does but formatting as an actual docstring has a practical usage. 

def approx_half(lowno, highno):
    """ Find integer approx halfway point between two values."""
    return int(round((lowno+highno)/2))


Enclosing the text in triple quotes when it's at the start of a function will make it a docstring, which means that people can access it in code or in the interpreter to investigate your description of it.

&gt;&gt;&gt; help(approx_half)
Help on function approx_half in module __main__:

approxhalf(lowno, highno)
    Find integer approx halfway point between two values.