The Haskell type class RealFloat has a reasonable number of operations to test for NaN, denormalized numbers, etc. You can also ask if the implementation uses IEEE.
-- Lennart On 8/4/07, Paul Johnson <[EMAIL PROTECTED]> wrote: > > Andrew Coppin wrote: > > Paul Johnson wrote: > >> > log 0 > >> -Infinity > > Oh. So... since when does Haskell know about infinity? > I should have mentioned that the underlying platform in my case is an > Intel P4. Haskell does not specify a floating point implementation; the > assumption is that it uses whatever the platform provides because > anything else would be horribly inefficient. The P4 implements IEEE > floating point, which as Andrew pointed out includes Infinity, -Infinity > and NaN as special cases of floating point values. It also seems to > distinguish between 0.0 and (-0.0), although they are still equal. For > instance: > > > (-0.0) > -0.0 > > > 1.0 / 0.0 > Infinity > > > 1.0 / (-0.0) > -Infinity > > (Aside: should Infinity etc. be included in the Haskell standard? Or > possibly in a Data.Numeric.IEEE extension? They look like constructors, > and it would be nice to be able to pattern match on them.) > > So if you tried these experiments on a non-IEEE platform then you would > get different results. You might get exceptions or just wierd big > numbers. ISTR someone posted results from a Sun Sparc along these lines > some time ago. > > foo x > > | x < 0 = ... > > | x == 0 = ... > > | x > 0 = ... > > I was most perplexed when I got a "non-exhaustive patterns" > > exception... It turns out there was a NaN in there. I forget about that. > Nasty. I'll have to bear that one in mind myself. > > You can detect infinities by equality, but not NaN. > > > let inf = (1.0 / 0.0) > > let nan = inf * 0.0 > > inf == inf > True > >nan == nan > False > > >> > exp (log 0 * 2) > >> 0.0 > > Well that's interesting. I did wonder why it *doesn't* break in the > > real case... > I haven't perused the IEEE standard, but I expect it defines something > like this: > > Infinity * 0 = NaN > Infinity * _ = Infinity > exp Infinity = Infinity > exp (-Infinity) = 0 > > Um... why would infinity * 0 be NaN? That doesn't make sense... > Infinity times anything is Infinity. Zero times anything is zero. So > what should Infinity * zero be? There isn't one right answer. In this > case the "morally correct" answer is zero, but in other contexts it > might be Infinity or even some finite number other than zero. > > Consider 0.0 / 0.0, which also evaluates to NaN. What should its value > be? If you take the limit of (x / x) as x -> 0 then the right answer is > 0. On the other hand if you take the limit of (0 / x) as x -> 0 then > the right answer is infinity. Worse yet, if you take the limit of (2x / > x) as x-> 0 then the right answer is 2. You can pick any finite or > infinite value you like. So the only possible answer is NaN. > > > >> So no, its not a bug, its according to the standard. > > > > So I'm the only person who was expecting zero squared to be zero? > > (IMHO the standard should try to implement mathematical operations in > > a mathematically sensible way...) > It does *try*. I'm not sure if IEEE arithmetic was actually defined > back in 98. It certainly wasn't widely implemented. There might well > be a case for revisiting the standard to allow for IEEE values, but you > can't mandate them because not all platforms support IEEE arithmetic. > >> While working through this I also came across the following case > >> which technically is a bug: > >> > >> > 0 ** 0 > >> 1.0 > >> > >> > exp (log 0 * 0) > >> NaN > >> > >> I suspect that GHCi is using a built-in exponentiation operator that > >> doesn't quite conform to the standard in this case. > > > > Now that really *is* odd... > When I said "built in" I meant "built in to the hardware". This is > probably another special case defined in the IEEE standard, which is not > the same as the Haskell 98 definition. > > The reason why the IEEE standard was defined in the first place was that > floating point software portability was being seriously limited by these > corner cases. You would get some numerical code working on a Sun, and > then find it broke on a PC because one of them defined (0.0 / 0.0) as 1 > and the other defined it as 0. Worse yet, you might find it worked on > Intel chips but not IBM or AMD. Programmers also had to code explicit > checks for division by zero and implement their own versions of Infinity > and NaN in cases where they might appear, which cluttered up the code > and slowed down execution. > > One way out of this morass would be to define Haskell floating point > arithmetic as IEEE standard, and document non-conformance for certain > platforms. In the long term that is probably the way forwards (do any > currently sold chips *not* implement IEEE?). It would also let us > include Infinity and NaN as constructors. However it would lead to > significant problems when compiling code that used these values on > non-IEEE platforms. What do you do then? > > Paul. > > _______________________________________________ > Haskell-Cafe mailing list > [email protected] > http://www.haskell.org/mailman/listinfo/haskell-cafe >
_______________________________________________ Haskell-Cafe mailing list [email protected] http://www.haskell.org/mailman/listinfo/haskell-cafe
