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