<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Clojure Q&amp;A - Recent questions tagged nan</title>
<link>https://ask.clojure.org/index.php/tag/nan</link>
<description></description>
<item>
<title>Incorrect result when evaluating `not=` on `##NaNs`</title>
<link>https://ask.clojure.org/index.php/14298/incorrect-result-when-evaluating-not-on-nans</link>
<description>&lt;p&gt;Alex Miller asked me to write this up here. I found a bug in clojure.core yesterday that involves &lt;code&gt;not=&lt;/code&gt; when used to compare NaNs. This was reported on Slack and the discussion is here:&lt;br&gt;
&lt;a rel=&quot;nofollow&quot; href=&quot;https://clojurians.slack.com/archives/C03S1KBA2/p1733612992809069&quot;&gt;https://clojurians.slack.com/archives/C03S1KBA2/p1733612992809069&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here is a more highly summarized version of the discussion from Slack (at least from my perspective). If we fire up the Clojure CLI, we can evaluate the following.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; Clojure 1.12.0
 user=&amp;gt; (= ##NaN ##NaN)
 false
 user=&amp;gt; (not= ##NaN ##NaN)
 false
 user=&amp;gt; (not (= ##NaN ##NaN))
 true
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem here is that &lt;code&gt;=&lt;/code&gt;, &lt;code&gt;not&lt;/code&gt;, and &lt;code&gt;not=&lt;/code&gt; have a relationship between them. Specifically, for any &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;, if &lt;code&gt;(= x y)&lt;/code&gt; returns a boolean, then &lt;code&gt;(not (= x y))&lt;/code&gt; should return the opposite boolean, and since &lt;code&gt;not=&lt;/code&gt; is defined as &lt;code&gt;(not (= x y))&lt;/code&gt;, it should return the same value as &lt;code&gt;(not (= x y))&lt;/code&gt; for all &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;. This doesn't happen if &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; are both &lt;code&gt;##NaN&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that there were a lot of calories burned on Slack with suggestions that doubles should never be compared for equality, that NaNs are shifty, not-quite-value objects and should be avoided, that anybody who wants to test for the presence of a NaN should use &lt;code&gt;NaN?&lt;/code&gt; which is already in clojure.core, and that the documentation around equality should be updated to say some of those things. Many of those statements are true or good practice. But all of them miss the broader point.&lt;/p&gt;
&lt;p&gt;This bug has nothing to do specifically to do with NaNs. It just seems that NaNs expose the bug. The real issue is with the contractual relationship between &lt;code&gt;=&lt;/code&gt;, &lt;code&gt;not&lt;/code&gt;, and &lt;code&gt;not=&lt;/code&gt; which appears to be violated in the presence of NaNs. Specifically, &lt;code&gt;not=&lt;/code&gt; is no longer referentially transparent with respect to &lt;code&gt;(not (= ...))&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On Slack, @potetm decompiled the code generated for these cases and found the following.&lt;/p&gt;
&lt;p&gt;For &lt;code&gt;(not= ##NaN ##NaN)&lt;/code&gt; :&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(clj-java-decompiler.core/decompile
  (not= ##NaN ##NaN))

// Decompiling class: cjd__init
import clojure.lang.*;

public class cjd__init
{
    public static final Var __not_EQ_;
    public static final Object const__1;
    
    public static void load() {
        ((IFn)cjd__init.__not_EQ_.getRawRoot()).invoke(cjd__init.const__1, cjd__init.const__1);
    }
    
    public static void __init0() {
        __not_EQ_ = RT.var(&quot;clojure.core&quot;, &quot;not=&quot;);
        const__1 = Double.NaN;
    }
    
    static {
        __init0();
        Compiler.pushNSandLoader(RT.classForName(&quot;cjd__init&quot;).getClassLoader());
        try {
            load();
            Var.popThreadBindings();
        }
        finally {
            Var.popThreadBindings();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then for &lt;code&gt;(not (= ##NaN ##NaN))&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(clj-java-decompiler.core/decompile
  (not (= ##NaN ##NaN)))

// Decompiling class: cjd__init
import clojure.lang.*;

public class cjd__init
{
    public static final Var __not;
    
    public static void load() {
        ((IFn)cjd__init.__not.getRawRoot()).invoke(Util.equiv(Double.NaN, Double.NaN) ? Boolean.TRUE : Boolean.FALSE);
    }
    
    public static void __init0() {
        __not = RT.var(&quot;clojure.core&quot;, &quot;not&quot;);
    }
    
    static {
        __init0();
        Compiler.pushNSandLoader(RT.classForName(&quot;cjd__init&quot;).getClassLoader());
        try {
            load();
            Var.popThreadBindings();
        }
        finally {
            Var.popThreadBindings();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It appears that the compiler optimizes the call to &lt;code&gt;=&lt;/code&gt; and does not box the &lt;code&gt;##NaN&lt;/code&gt; values when compiling &lt;code&gt;(not (= ##NaN ##NaN))&lt;/code&gt;, whereas the call to &lt;code&gt;not=&lt;/code&gt; receives the &lt;code&gt;##NaN&lt;/code&gt;s boxed as Doubles. This then causes a subsequent call to &lt;code&gt;clojure.lang.Util/equiv&lt;/code&gt; (after following the call chain through &lt;code&gt;not=&lt;/code&gt; -&amp;gt; &lt;code&gt;=&lt;/code&gt; -&amp;gt; &lt;code&gt;clojure.lang.Util/equiv&lt;/code&gt;) to return &lt;code&gt;true&lt;/code&gt; improperly (since NaNs are never equal to anything, even themselves).&lt;/p&gt;
&lt;p&gt;IMO, this is a bug, albeit a low priority one. Most programmers successfully use floating point math without ever having to deal with NaNs. While NaNs seem to trigger the bug, there may be other cases that also trigger it. I can't speak to that.&lt;/p&gt;
</description>
<category>Compiler</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14298/incorrect-result-when-evaluating-not-on-nans</guid>
<pubDate>Sun, 08 Dec 2024 21:14:02 +0000</pubDate>
</item>
<item>
<title>##NaN on map keys, what to expect?</title>
<link>https://ask.clojure.org/index.php/12128/nan-on-map-keys-what-to-expect</link>
<description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Doing some tests and arrived at the following scenario:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(assoc {##NaN nil} ##NaN nil)
=&amp;gt; {##NaN nil, ##NaN nil}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;but trying to create a map like this is not possible:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{##NaN nil, ##NaN 1}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Could this be a bug in assoc? or is this the expected behavior&lt;/p&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/12128/nan-on-map-keys-what-to-expect</guid>
<pubDate>Thu, 25 Aug 2022 14:40:19 +0000</pubDate>
</item>
</channel>
</rss>