Verifiably better, validated Enum for Python

Steve D'Aprano steve+python at pearwood.info
Fri May 26 19:28:10 EDT 2017


On Fri, 26 May 2017 10:01 pm, Chris Angelico wrote:

>> That's not how the C standard defines "undefined behaviour", or the
>> implication of such.
> 
> Can you explain to me how it's different? Either way, the
> implementation is allowed to do what it likes, because you shouldn't
> be doing that.

I don't know whether "implementation defined behaviour" is actually defined
by the C standard, but the common meaning of it (the way people expect
implementation dependent code to behave) is that it is legal code, but the
actual result may vary from one machine or platform to another.

For example, in Python something like math.sin(1.2345) is implementation
dependent. For technical reasons, guaranteeing correctly rounded results
for trigonometric functions is too hard, so in IEEE 754 the guarantee is
weakened. (Let alone for platforms that don't use IEEE 754 semantics!)
Consequently, you can expect that:

- the result will be *approximately* equal to the true mathematical result;

- but there is no guarantee of how close it will be;

- and consequently sin(1.2345) may return slightly different results on
different platforms.

If you code requires that sin(1.2345) == 0.9439833239445111 exactly, you're
living in sin, because that's an implementation dependent result. But its
only a venal sin, because you can still reason about your program. For
example, you can correct expect that after:

    x = math.sin(1.2345)
    y = x*2
    if y > 10.0:
        os.system("rm -r /")  # Erase hard drive.
    else:
        print(y)

y will be a float between -2.0 and +2.0 and so your hard drive is safe.

But that's not what the C standard means by undefined behaviour. Let us
pretend that Python's compiler performed aggressive optimizations like C
compilers often do, and further more let us pretend that Python defined
sin(1.2345) as undefined behaviour in the C sense. The Python compiler
would be permitted to reason thusly:

    math.sin(1.2345) is undefined, so no valid program can contain 
    that particular function call. If it does, I don't have to halt
    compilation and raise SyntaxError (although I can if I so wish),
    but can do my best to make the program valid.

    Six pages later, in another function, there's some code I wish
    to optimize, and I can do so if x > 7.5. Since math.sin(1.2345)
    is undefined, I can say that x is some arbitrary value greater
    than 7.5, and that will satisfy the code written and allow the
    optimization.

    Since x is known, I know that y must be greater than 15, and
    since 15 > 10, I can optimize the entire block to:

    x = 987.0  # any value greater than 7.5 is as good as any other...
    os.system("rm -r /")  # erase hard drive

    and emit byte code for that.



More to follow.



-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list