On Sun, 03 Jul 2005 15:46:35 +0100, Tom Anderson wrote: > I think there would be a lot less confusion over the alleged inaccuracy of > floating point if everyone wrote in hex - indeed, i believe that C99 has > hex floating-point literals. C has always been such a forward-thinking > language!
No, all that would do is shift the complaint from "Python has a bug when you divide 10 into 1.0" to "Python has a bug when you convert 0.1 into hex". [snip] >> But this works: >> >> py> inf = float("inf") >> py> inf >> inf > > True. Still, i'd rather not have to rely on string parsing to generate a > fairly fundamental arithmetic quantity. What happens when your Python script is running on a platform that can deal with 1e300*1e300 giving 1e600 without overflow? Okay, maybe no such platform exists today (or does it?), but it could exist, and your code will fail on those systems. I believe that the IEEE standard specifies that float("inf") should give an infinity, just as float("0.0") should give a zero. For production code, I'd wrap float("inf") in a try...except and only fall back on your method if it raised an exception, and then I'd actually test that your result was a real inf (eg by testing that inf+inf=inf). [snip] >>> The IEEE spec actually says that (x == nan) should be *false* for every x, >>> including nan. I'm not sure if this is more or less stupid than what >>> python does! >> >> Well, no, the IEEE standard is correct. NaNs aren't equal to anything, >> including themselves, since they aren't numbers. > > I don't buy that. Just because something isn't a number doesn't mean it > can't be equal to something else, does it? I mean, we even say x == None > if x is indeed None. Yes, but None does equal None, since there is only one None, and by definition, a thing is equal to itself. But NaNs are _not_ things. That is the whole point! Yes, we _represent_ INF-INF as a particular bit-pattern and call it NaN, but mathematically subtracting infinity from infinity is not defined. There is no answer to the question "what is infinity subtracted from infinity?". We pretend that the answer is NaN, but that isn't right. The NaN is just there as a placeholder for "there is no answer", so that we don't have to sprinkle our code with a thousand and one tests. Since INF-INF doesn't have an answer, we can't do this: x = inf - inf y = inf - inf and expect that x == y. > Moreover, this freaky rule about NaNs means that this > is an exception to the otherwise absolutely inviolate law that x == x. Yes. So what? Remove the NaN shorthand: "The non-existent answer to this question is the same non-existent answer to this other question." It doesn't make sense to say that a non-thing is equal to anything -- even to itself, since itself doesn't exist. (Remember, a NaN is just an illusionary placeholder, not a number.) > I'd rather have that simple, fundamental logical consistency than some IEEE > rocket scientist's practical-value-free idea of mathematical consistency. Ah, from a _programmer's_ perspective, there is an argument that the simplicity of just testing NaNs with equality outweighs the logical silliness of doing such a thing. But, apart from testing whether a float is a NaN, why would you ever want to do an equality test? The only usage case I can think of is would be something like this: def isNaN(x): return x == SOME_KNOWN_NAN But that won't work, because there are lots of different NaNs. 254 of them, or twice that if you include signed NaNs (which you shouldn't, but you do have to allow for them in equality testing). Any good IEEE compliant system should already have a built-in function that tests for NaNs. [snip] >>> And while i'm ranting, how come these expressions aren't the same: >>> >>> 1e300 * 1e300 >>> 1e300 ** 2 >> >> Because this is floating point, not real maths :-) >> >> I get inf and Overflow respectively. What do you get? > > The same. They really ought to give the same answer. In real numbers, yes they should. In floating point, that is too much to expect. In mathematics, the order you do your calculation shouldn't matter. But in floating point, where there is rounding errors and finite precision issues, it does. The aim of the High Level Language designer is to insulate the programmer from the ickiness of actual hardware implementation. Unfortunately, in the case of floating point, you can't get away from the hardware limitations. >>> And finally, does Guido know something about arithmetic that i don't, >>> or is this expression: >>> >>> -1.0 ** 0.5 >>> >>> Evaluated wrongly? >> >> No, it is evaluated according to the rules of precedence. It is >> equivalent to -(1.0**0.5). You are confusing it with (-1.0)**0.5 which >> fails as expected. > > Ah. My mistake. I submit that this is also a bug in python's grammar. > There's probably some terribly good reason for it, though. Yes. You generally want exponentiation to have the highest precedence. 2*3**4 should give 162, not 1296. Think about how you would write that mathematically, with pencil and paper: the 4 is written as a superscript over the 3, and is applied to that before multiplying by the 2. Unary minus is equivalent to multiplying by -1, so -3**4 is equivalent to -1*3**4. These are the rules of precedence mathematicians have worked out over many centuries. Yes, some of them are arbitrary choices, but they do work, and changing them for another arbitrary choice doesn't give us any benefit. -- Steven. -- http://mail.python.org/mailman/listinfo/python-list