Boost C++ Libraries: Ticket #9966: exponential_distribution returns negative zero https://svn.boost.org/trac10/ticket/9966 <p> The code below produces this output: </p> <p> 1.72296<br /> -0<br /> 0.295209<br /> 0.210905<br /> 0.930678<br /> </p> <div class="wiki-code"><div class="code"><pre><span class="cp">#include</span> <span class="cpf">&lt;fstream&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;boost/random.hpp&gt;</span><span class="cp"></span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">boost</span><span class="o">::</span><span class="n">random</span><span class="p">;</span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> <span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> <span class="n">ifstream</span> <span class="n">mtfile</span><span class="p">;</span> <span class="n">mtfile</span><span class="p">.</span><span class="n">open</span><span class="p">(</span><span class="s">&quot;mt.dat&quot;</span><span class="p">);</span> <span class="c1">//see attached file</span> <span class="n">mt19937</span> <span class="n">mt</span><span class="p">;</span> <span class="n">mtfile</span> <span class="o">&gt;&gt;</span> <span class="n">mt</span><span class="p">;</span> <span class="n">mtfile</span><span class="p">.</span><span class="n">close</span><span class="p">();</span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">exponential_distribution</span><span class="o">&lt;</span><span class="kt">float</span><span class="o">&gt;</span><span class="p">(</span><span class="mf">1.f</span><span class="p">)(</span><span class="n">mt</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="p">}</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </pre></div></div> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/9966 Trac 1.4.3 mazzamuto@… Wed, 30 Apr 2014 10:24:45 GMT attachment set https://svn.boost.org/trac10/ticket/9966 https://svn.boost.org/trac10/ticket/9966 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">mt.dat</span> </li> </ul> <p> generator state </p> Ticket mazzamuto@… Mon, 07 Jul 2014 16:37:01 GMT version, summary changed https://svn.boost.org/trac10/ticket/9966#comment:1 https://svn.boost.org/trac10/ticket/9966#comment:1 <ul> <li><strong>version</strong> <span class="trac-field-old">Boost 1.55.0</span> → <span class="trac-field-new">Boost 1.48.0</span> </li> <li><strong>summary</strong> <span class="trac-field-old">exponential_distribution returns negative zero with single precision float</span> → <span class="trac-field-new">exponential_distribution returns negative zero</span> </li> </ul> Ticket mazzamuto@… Mon, 07 Jul 2014 16:38:11 GMT attachment set https://svn.boost.org/trac10/ticket/9966 https://svn.boost.org/trac10/ticket/9966 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">mt_double.dat</span> </li> </ul> Ticket anonymous Mon, 07 Jul 2014 16:47:35 GMT <link>https://svn.boost.org/trac10/ticket/9966#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9966#comment:2</guid> <description> <p> The bug appears also with double precision floats. The code below produces this output: </p> <pre class="wiki">2.298 -0 1.22475 1.07758 0.66385 </pre><div class="wiki-code"><div class="code"><pre><span class="cp">#include</span> <span class="cpf">&lt;fstream&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;boost/random.hpp&gt;</span><span class="cp"></span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">boost</span><span class="o">::</span><span class="n">random</span><span class="p">;</span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> <span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> <span class="n">ifstream</span> <span class="n">mtfile</span><span class="p">;</span> <span class="n">mtfile</span><span class="p">.</span><span class="n">open</span><span class="p">(</span><span class="s">&quot;mt_double.dat&quot;</span><span class="p">);</span> <span class="c1">//see attached file</span> <span class="n">mt19937</span> <span class="n">mt</span><span class="p">;</span> <span class="n">mtfile</span> <span class="o">&gt;&gt;</span> <span class="n">mt</span><span class="p">;</span> <span class="n">mtfile</span><span class="p">.</span><span class="n">close</span><span class="p">();</span> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">exponential_distribution</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span><span class="p">(</span><span class="mf">1.f</span><span class="p">)(</span><span class="n">mt</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="p">}</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </pre></div></div> </description> <category>Ticket</category> </item> <item> <dc:creator>Steven Watanabe</dc:creator> <pubDate>Fri, 27 Feb 2015 00:53:24 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9966#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9966#comment:3</guid> <description> <p> I don't consider returning -0 to be a bug, since 0 == -0. The real problem is that it's returning 0 at all. According to C++11 exponential_distribution returns values &gt; 0. </p> </description> <category>Ticket</category> </item> <item> <author>mazzamuto@…</author> <pubDate>Fri, 27 Feb 2015 11:39:09 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9966#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9966#comment:4</guid> <description> <p> I agree that the problem is not with the sign. Indeed I recognize that the documentation states: The domain of the random variable is [0, +Inf]. So, returning zero is expected and documented even if this clashes with C++11. Apparently this behaviour results from this code </p> <div class="wiki-code"><div class="code"><pre><span class="k">return</span> <span class="o">-</span><span class="n">result_type</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">/</span> <span class="n">_lambda</span> <span class="o">*</span> <span class="n">log</span><span class="p">(</span><span class="n">result_type</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">-</span><span class="n">uniform_01</span><span class="o">&lt;</span><span class="n">RealType</span><span class="o">&gt;</span><span class="p">()(</span><span class="n">eng</span><span class="p">));</span> </pre></div></div><p> where the log argument is (0,1] instead of [0,1). </p> <p> This causes another problem with the upper limit +Inf being documented as included. For example, this code should produce the minimum and maximum values obtainable from exponential_distribution with lambda=1: </p> <div class="wiki-code"><div class="code"><pre><span class="cp">#include</span> <span class="cpf">&lt;boost/random.hpp&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;boost/version.hpp&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;math.h&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp"></span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">boost</span><span class="o">::</span><span class="n">random</span><span class="p">;</span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> <span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;Using BOOST &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">BOOST_VERSION</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;---------------&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="n">mt19937</span><span class="o">*</span> <span class="n">mt</span> <span class="o">=</span> <span class="k">new</span> <span class="n">mt19937</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="k">for</span> <span class="p">(</span><span class="n">u_int32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="n">mt</span><span class="o">-&gt;</span><span class="n">min</span><span class="p">();</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span> <span class="kt">double</span> <span class="n">factor</span> <span class="o">=</span> <span class="mf">1.</span><span class="o">/</span><span class="p">(</span><span class="n">mt</span><span class="o">-&gt;</span><span class="n">max</span><span class="p">()</span><span class="o">-</span><span class="n">mt</span><span class="o">-&gt;</span><span class="n">min</span><span class="p">()</span><span class="o">+</span><span class="mf">1.</span><span class="p">);</span> <span class="kt">double</span> <span class="n">xi</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span><span class="o">-</span><span class="n">mt</span><span class="o">-&gt;</span><span class="n">min</span><span class="p">())</span><span class="o">*</span><span class="n">factor</span><span class="p">;</span> <span class="n">printf</span><span class="p">(</span><span class="s">&quot;%.20f</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.f</span><span class="o">/</span><span class="mf">1.f</span><span class="o">*</span><span class="n">log</span><span class="p">(</span><span class="mf">1.f</span><span class="o">-</span><span class="n">xi</span><span class="p">));</span> <span class="p">}</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;---------------&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="k">for</span> <span class="p">(</span><span class="n">u_int32_t</span> <span class="n">i</span> <span class="o">=</span> <span class="n">mt</span><span class="o">-&gt;</span><span class="n">max</span><span class="p">();</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">mt</span><span class="o">-&gt;</span><span class="n">max</span><span class="p">()</span> <span class="o">-</span> <span class="mi">5</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span> <span class="p">{</span> <span class="kt">double</span> <span class="n">factor</span> <span class="o">=</span> <span class="mf">1.</span><span class="o">/</span><span class="p">(</span><span class="n">mt</span><span class="o">-&gt;</span><span class="n">max</span><span class="p">()</span><span class="o">-</span><span class="n">mt</span><span class="o">-&gt;</span><span class="n">min</span><span class="p">()</span><span class="o">+</span><span class="mf">1.</span><span class="p">);</span> <span class="kt">double</span> <span class="n">xi</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span><span class="o">-</span><span class="n">mt</span><span class="o">-&gt;</span><span class="n">min</span><span class="p">())</span><span class="o">*</span><span class="n">factor</span><span class="p">;</span> <span class="n">printf</span><span class="p">(</span><span class="s">&quot;%.20f</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="o">-</span><span class="mf">1.f</span><span class="o">/</span><span class="mf">1.f</span><span class="o">*</span><span class="n">log</span><span class="p">(</span><span class="mf">1.f</span><span class="o">-</span><span class="n">xi</span><span class="p">));</span> <span class="p">}</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </pre></div></div><p> The output is: </p> <pre class="wiki">Using BOOST 105700 --------------- -0.00000000000000000000 0.00000000023283064368 0.00000000046566128742 0.00000000069849193121 0.00000000093132257505 --------------- 22.18070977791824915926 21.48756259735830553836 21.08209748925014181964 20.79441541679835836476 20.57127186548414954359 </pre><p> and we can see that the maximum value is 22, not +Inf. The maximum value shifts accordingly to 44 when using mt19937_64, u_int64_t and long double. </p> <p> Taking the log argument as [0,1) should fix both problems: </p> <pre class="wiki">Using BOOST 105700 --------------- inf 22.18070977791824915926 21.48756259735830553836 21.08209748925014181964 20.79441541679835836476 --------------- 0.00000000023283064368 0.00000000046566128742 0.00000000069849193121 0.00000000093132257505 0.00000000116415321895 </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>Steven Watanabe</dc:creator> <pubDate>Fri, 27 Feb 2015 15:48:58 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9966#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9966#comment:5</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/9966#comment:4" title="Comment 4">mazzamuto@…</a>: </p> <blockquote class="citation"> <p> I agree that the problem is not with the sign. Indeed I recognize that the documentation states: The domain of the random variable is [0, +Inf]. </p> </blockquote> <p> Which documentation? I don't see any such statement in the Boost.Random docs. </p> <blockquote class="citation"> <p> This causes another problem with the upper limit +Inf being documented as included. For example, this code should produce the minimum and maximum values obtainable from exponential_distribution with lambda=1: </p> </blockquote> <p> An exponential_distribution should never produce +Inf. Theoretically, lim_{x-&gt;\inf} p(x) = 0, so while the values can be arbitrarily large, the distribution should never produce infinity. We have to approximate the distribution, because floating point cannot represent every real number, but adding +Inf as a possible output would severely bias the distribution (i.e. the mean would become +Inf). I can't think of any circumstances where I would want it to return +Inf. </p> </description> <category>Ticket</category> </item> <item> <author>mazzamuto@…</author> <pubDate>Fri, 27 Feb 2015 22:11:35 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9966#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9966#comment:6</guid> <description> <p> Thanks for your help, I understand what you say on +Inf and about the approximation. I must say that I haven't used BOOST extensively, so there may be some things that I'm missing. Anyways the problem in the OP did cause a bug in a section of my code which wasn't expecting 0 from exponential_distribution. I fixed it with an additional check. </p> <p> I was referring to this documentation page <a href="http://www.boost.org/doc/libs/1_57_0/libs/math/doc/html/math_toolkit/dist_ref/dists/exp_dist.html">http://www.boost.org/doc/libs/1_57_0/libs/math/doc/html/math_toolkit/dist_ref/dists/exp_dist.html</a> where it says: The domain of the random variable is [0, +∞]. Anyways I get this output when I ask the range of the distribution. Is the interval open or closed? Is it possibile to generate numbers in an open-open interval with BOOST? Thanks again. </p> <pre class="wiki">range of exponential_distribution: 0 inf </pre><div class="wiki-code"><div class="code"><pre><span class="cp">#include</span> <span class="cpf">&lt;boost/version.hpp&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;boost/math/distributions/exponential.hpp&gt;</span><span class="cp"></span> <span class="cp">#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp"></span> <span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span> <span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;Using BOOST &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">BOOST_VERSION</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;---------------&quot;</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="n">boost</span><span class="o">::</span><span class="n">math</span><span class="o">::</span><span class="n">exponential_distribution</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">ed</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="n">pair</span><span class="o">&lt;</span><span class="kt">double</span><span class="p">,</span> <span class="kt">double</span><span class="o">&gt;</span> <span class="n">r</span> <span class="o">=</span> <span class="n">boost</span><span class="o">::</span><span class="n">math</span><span class="o">::</span><span class="n">range</span><span class="p">(</span><span class="n">ed</span><span class="p">);</span> <span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="s">&quot;range of exponential_distribution: &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">r</span><span class="p">.</span><span class="n">first</span> <span class="o">&lt;&lt;</span> <span class="s">&quot; &quot;</span> <span class="o">&lt;&lt;</span> <span class="n">r</span><span class="p">.</span><span class="n">second</span> <span class="o">&lt;&lt;</span> <span class="n">endl</span><span class="p">;</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </pre></div></div> </description> <category>Ticket</category> </item> <item> <dc:creator>Steven Watanabe</dc:creator> <pubDate>Fri, 27 Feb 2015 23:13:00 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9966#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9966#comment:7</guid> <description> <p> It looks like all standard library implementations are essentially similar to Boost.Random. I checked msvc 2013, gcc 4.8.3, and libc++ ToT. The only difference is that libstdc++ and libc++ use generate_canonical. They all use -log(1 - X)/lambda were X is a uniform variate in [0, 1) and can therefore produce the value 0. </p> </description> <category>Ticket</category> </item> </channel> </rss>