<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/class.random-randomizer.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'de',
  ),
  'this' => 
  array (
    0 => 'random-randomizer.getfloat.php',
    1 => 'Random\\Randomizer::getFloat',
    2 => 'Get a uniformly selected float',
  ),
  'up' => 
  array (
    0 => 'class.random-randomizer.php',
    1 => 'Random\\Randomizer',
  ),
  'prev' => 
  array (
    0 => 'random-randomizer.getbytesfromstring.php',
    1 => 'Random\\Randomizer::getBytesFromString',
  ),
  'next' => 
  array (
    0 => 'random-randomizer.getint.php',
    1 => 'Random\\Randomizer::getInt',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'en',
    'path' => 'reference/random/random/randomizer/getfloat.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="random-randomizer.getfloat" class="refentry">
 <div class="refnamediv">
  <h1 class="refname">Random\Randomizer::getFloat</h1>
  <p class="verinfo">(PHP 8 &gt;= 8.3.0)</p><p class="refpurpose"><span class="refname">Random\Randomizer::getFloat</span> &mdash; <span class="dc-title">Get a uniformly selected float</span></p>

 </div>

 <div class="refsect1 description" id="refsect1-random-randomizer.getfloat-description">
  <h3 class="title">Beschreibung</h3>
  <div class="methodsynopsis dc-description">
   <span class="modifier">public</span> <span class="methodname"><strong>Random\Randomizer::getFloat</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.float.php" class="type float">float</a></span> <code class="parameter">$min</code></span>, <span class="methodparam"><span class="type"><a href="language.types.float.php" class="type float">float</a></span> <code class="parameter">$max</code></span>, <span class="methodparam"><span class="type"><a href="enum.random-intervalboundary.php" class="type Random\IntervalBoundary">Random\IntervalBoundary</a></span> <code class="parameter">$boundary</code><span class="initializer"> = <strong><code>Random\IntervalBoundary::ClosedOpen</code></strong></span></span>): <span class="type"><a href="language.types.float.php" class="type float">float</a></span></div>

  <p class="para rdfs-comment">
   Returns a uniformly selected, equidistributed float from a requested interval.
  </p>
  <p class="para">
   Due to the limited precision, not all real numbers can be exactly represented as
   a floating point number.

   If a number cannot be represented exactly, it is rounded to the nearest
   representable exact value.

   Furthermore, floats are not equally dense across the whole number line.

   Because floats use a binary exponent, the distance between two neighboring
   floats doubles at each power of two.

   In other words: There are the same number of representable floats between
   <code class="literal">1.0</code> and <code class="literal">2.0</code>
   as they are between
   <code class="literal">2.0</code> and <code class="literal">4.0</code>,
   <code class="literal">4.0</code> and <code class="literal">8.0</code>,
   <code class="literal">8.0</code> and <code class="literal">16.0</code>,
   and so on.
  </p>
  <p class="para">
   Randomly sampling an arbitrary number within the requested interval, for example
   by dividing two integers, might result in a biased distribution for this reason.

   The necessary rounding will cause some floats to be returned more often than
   others, especially around powers of two when the density of floats changes.
  </p>
  <p class="para">
   <span class="methodname"><strong>Random\Randomizer::getFloat()</strong></span> implements an algorithm that
   will return a uniformly selected float from the largest possible set of exactly
   representable and equidistributed floats within the requested interval.

   The distance between the selectable floats (“step size”) matches the distance
   between the floats with the lowest density, i.e. the distance between floats
   at interval boundary with the larger absolute value.

   This means that not all representable floats within a given interval may be
   returned if the interval crosses one or more powers of two.

   Stepping will start from the interval boundary with the larger absolute value
   to ensure the steps align with the exactly representable floats.
  </p>
  <p class="para">
   Closed interval boundaries will always be included in the set of selectable
   floats.

   Thus, if the size of the interval is not an exact multiple of the step size and
   the boundary with the smaller absolute value is a closed boundary, the distance
   between that boundary and its nearest selectable float will be smaller than the
   step size.
  </p>
  <div class="caution"><strong class="caution">Achtung</strong>
   <p class="para">
    Post-processing the returned floats is likely going to break the uniform
    equidistribution, because the intermediate floats within a mathematical
    operation are experiencing implicit rounding.

    The requested interval should match the desired interval as closely as possible
    and rounding should only be performed as an explicit operation right before
    displaying the selected number to a user.
   </p>
  </div>
  <div class="refsect2 unknown-28" id="refsect2-random-randomizer.getfloat-unknown-28">
   <h4 class="title">Explanation of the Algorithm Using Example Values</h4>
   <p class="para">
    To give an example of how the algorithm works, consider a floating point
    representation that uses a 3-bit mantissa.

    This representation is capable of representing 8 different floating point
    values between consecutive powers of two.

    This means that between
    <code class="literal">1.0</code> and <code class="literal">2.0</code> all steps of size <code class="literal">0.125</code>
    are exactly representable and between <code class="literal">2.0</code> and <code class="literal">4.0</code>
    all steps of size <code class="literal">0.25</code> are exactly representable.

    In reality PHP’s floats use a 52-bit mantissa and can represent 2<sup class="superscript">52</sup>
    different values between each power of two.

    This means that
    <ul class="simplelist">
     <li><code class="literal">1.0</code></li>
     <li><code class="literal">1.125</code></li>
     <li><code class="literal">1.25</code></li>
     <li><code class="literal">1.375</code></li>
     <li><code class="literal">1.5</code></li>
     <li><code class="literal">1.625</code></li>
     <li><code class="literal">1.75</code></li>
     <li><code class="literal">1.875</code></li>
     <li><code class="literal">2.0</code></li>
     <li><code class="literal">2.25</code></li>
     <li><code class="literal">2.5</code></li>
     <li><code class="literal">2.75</code></li>
     <li><code class="literal">3.0</code></li>
     <li><code class="literal">3.25</code></li>
     <li><code class="literal">3.5</code></li>
     <li><code class="literal">3.75</code></li>
     <li><code class="literal">4.0</code></li>
    </ul>
    are the exactly representable floats between <code class="literal">1.0</code>
    and <code class="literal">4.0</code>.
   </p>
   <p class="para">
    Now consider that <code class="code">$randomizer-&gt;getFloat(1.625, 2.5, IntervalBoundary::ClosedOpen)</code>
    is called, i.e. a random float starting at <code class="literal">1.625</code> until, but not including,
    <code class="literal">2.5</code> is requested.

    The algorithm first determines the step size at the boundary with the larger absolute
    value (<code class="literal">2.5</code>). The step size at that boundary is <code class="literal">0.25</code>.
   </p>
   <p class="para">
    Note that the size of the requested interval is <code class="literal">0.875</code>, which is
    not an exact multiple of <code class="literal">0.25</code>.

    If the algorithm would start stepping at the lower bound <code class="literal">1.625</code>, it
    would encounter <code class="literal">2.125</code>, which is not exactly representable and would
    experience implicit rounding.

    Thus the algorithm starts stepping at the upper boundary <code class="literal">2.5</code>.

    The selectable values are:
    <ul class="simplelist">
     <li><code class="literal">2.25</code></li>
     <li><code class="literal">2.0</code></li>
     <li><code class="literal">1.75</code></li>
     <li><code class="literal">1.625</code></li>
    </ul>

    <code class="literal">2.5</code> is not included, because the upper boundary of the requested
    interval is an open boundary.

    <code class="literal">1.625</code> is included, even though its distance to the nearest value
    <code class="literal">1.75</code> is <code class="literal">0.125</code>, which is smaller than the
    previously determined step size of <code class="literal">0.25</code>.

    The reason for that is that the requested interval is closed at the lower boundary
    (<code class="literal">1.625</code>) and closed boundaries are always included.
   </p>
   <p class="para">
    Finally the algorithm uniformly selects one of the four selectable values at random
    and returns it.
   </p>
   <div class="refsect3 unknown-31" id="random-randomizer.getfloat.affine-transformation">
    <h5 class="title">Why Dividing Two Integers Does Not Work</h5>
    <p class="para">
     In the previous example, there are eight representable floating point numbers
     between each sub-interval delimited by a power of two.

     To give an example why dividing two integers would not work well to generate
     a random float, consider that there are 16 equidistributed floating point numbers
     in the right-open interval from <code class="literal">0.0</code> until, but not including,
     <code class="literal">1.0</code>. Half of them are the eight exactly representable values
     between <code class="literal">0.5</code> and <code class="literal">1.0</code>, the other half are the
     values between <code class="literal">0.0</code> and <code class="literal">1.0</code> that the step
     size of <code class="literal">0.0625</code>.

     These can easily be generated by dividing a random integer between <code class="literal">0</code>
     and <code class="literal">15</code> by <code class="literal">16</code> to obtain one of:

     <ul class="simplelist">
      <li><code class="literal">0.0</code></li>
      <li><code class="literal">0.0625</code></li>
      <li><code class="literal">0.125</code></li>
      <li><code class="literal">0.1875</code></li>
      <li><code class="literal">0.25</code></li>
      <li><code class="literal">0.3125</code></li>
      <li><code class="literal">0.375</code></li>
      <li><code class="literal">0.4375</code></li>
      <li><code class="literal">0.5</code></li>
      <li><code class="literal">0.5625</code></li>
      <li><code class="literal">0.625</code></li>
      <li><code class="literal">0.6875</code></li>
      <li><code class="literal">0.75</code></li>
      <li><code class="literal">0.8125</code></li>
      <li><code class="literal">0.875</code></li>
      <li><code class="literal">0.9375</code></li>
     </ul>
    </p>
    <p class="para">
     This random float could be scaled to right-open interval from <code class="literal">1.625</code>
     until, but not including, <code class="literal">2.75</code> by multiplying it with the size
     of the interval (<code class="literal">0.875</code>) and adding the minimum <code class="literal">1.625</code>.
     This so-called affine transformation would result in the values:

     <ul class="simplelist">
      <li><code class="literal">1.625</code> rounded to <code class="literal">1.625</code></li>
      <li><code class="literal">1.679</code> rounded to <code class="literal">1.625</code></li>
      <li><code class="literal">1.734</code> rounded to <code class="literal">1.75</code></li>
      <li><code class="literal">1.789</code> rounded to <code class="literal">1.75</code></li>
      <li><code class="literal">1.843</code> rounded to <code class="literal">1.875</code></li>
      <li><code class="literal">1.898</code> rounded to <code class="literal">1.875</code></li>
      <li><code class="literal">1.953</code> rounded to <code class="literal">2.0</code></li>
      <li><code class="literal">2.007</code> rounded to <code class="literal">2.0</code></li>
      <li><code class="literal">2.062</code> rounded to <code class="literal">2.0</code></li>
      <li><code class="literal">2.117</code> rounded to <code class="literal">2.0</code></li>
      <li><code class="literal">2.171</code> rounded to <code class="literal">2.25</code></li>
      <li><code class="literal">2.226</code> rounded to <code class="literal">2.25</code></li>
      <li><code class="literal">2.281</code> rounded to <code class="literal">2.25</code></li>
      <li><code class="literal">2.335</code> rounded to <code class="literal">2.25</code></li>
      <li><code class="literal">2.390</code> rounded to <code class="literal">2.5</code></li>
      <li><code class="literal">2.445</code> rounded to <code class="literal">2.5</code></li>
     </ul>

     Note how the upper boundary of <code class="literal">2.5</code> would be returned, despite
     being an open boundary and thus being excluded.

     Also note how <code class="literal">2.0</code> and <code class="literal">2.25</code> are twice as
     likely to be returned compared to the other values.
    </p>
   </div>

  </div>

 </div>


 <div class="refsect1 parameters" id="refsect1-random-randomizer.getfloat-parameters">
  <h3 class="title">Parameter-Liste</h3>
  <p class="para">
   <dl>
    
     <dt><code class="parameter">min</code></dt>
     <dd>
      <p class="para">
       The lower bound of the interval.
      </p>
     </dd>
    
    
     <dt><code class="parameter">max</code></dt>
     <dd>
      <p class="para">
       The upper bound of the interval.
      </p>
     </dd>
    
    
     <dt><code class="parameter">boundary</code></dt>
     <dd>
      <p class="para">
       Specifies whether the interval boundaries are possible return values.
      </p>
     </dd>
    
   </dl>
  </p>
 </div>


 <div class="refsect1 returnvalues" id="refsect1-random-randomizer.getfloat-returnvalues">
  <h3 class="title">Rückgabewerte</h3>
  <p class="para">
   A uniformly selected, equidistributed float from the interval specified by <code class="parameter">min</code>,
   <code class="parameter">max</code>, and <code class="parameter">boundary</code>.

   Whether <code class="parameter">min</code> and <code class="parameter">max</code> are possible return values depends
   on the value of <code class="parameter">boundary</code>.
  </p>
 </div>


 <div class="refsect1 errors" id="refsect1-random-randomizer.getfloat-errors">
  <h3 class="title">Fehler/Exceptions</h3>
  <ul class="itemizedlist">
   <li class="listitem">
    <span class="simpara">
     If the value of <code class="parameter">min</code> is not finite (<span class="function"><a href="function.is-finite.php" class="function">is_finite()</a></span>),
     a <span class="classname"><a href="class.valueerror.php" class="classname">ValueError</a></span> will be thrown.
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     If the value of <code class="parameter">max</code> is not finite (<span class="function"><a href="function.is-finite.php" class="function">is_finite()</a></span>),
     a <span class="classname"><a href="class.valueerror.php" class="classname">ValueError</a></span> will be thrown.
    </span>
   </li>
   <li class="listitem">
    <span class="simpara">
     If the requested interval does not contain any values,
     a <span class="classname"><a href="class.valueerror.php" class="classname">ValueError</a></span> will be thrown.
    </span>
   </li>
   
 <li class="listitem">
  <span class="simpara">
   Alle <span class="classname"><a href="class.throwable.php" class="classname">Throwable</a></span>s, die von der Methode <span class="methodname"><a href="random-engine.generate.php" class="methodname">Random\Engine::generate()</a></span> der
   zugrundeliegenden <a href="class.random-randomizer.php#random-randomizer.props.engine" class="link"><code class="literal">Random\Randomizer::$engine</code></a> ausgelöst werden.
  </span>
 </li>

  </ul>
 </div>


 <div class="refsect1 examples" id="refsect1-random-randomizer.getfloat-examples">
  <h3 class="title">Beispiele</h3>
  <div class="example" id="example-1">
   <p><strong>Beispiel #1 <span class="methodname"><strong>Random\Randomizer::getFloat()</strong></span> example</strong></p>
   <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br />$randomizer </span><span style="color: #007700">= new </span><span style="color: #0000BB">\Random\Randomizer</span><span style="color: #007700">();<br /><br /></span><span style="color: #FF8000">// Note that the latitude granularity is double the<br />// longitude’s granularity.<br />//<br />// For the latitude the value may be both -90 and 90.<br />// For the longitude the value may be 180, but not -180, because<br />// -180 and 180 refer to the same longitude.<br /></span><span style="color: #0000BB">printf</span><span style="color: #007700">(<br />    </span><span style="color: #DD0000">"Lat: %+.6f Lng: %+.6f"</span><span style="color: #007700">,<br />    </span><span style="color: #0000BB">$randomizer</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getFloat</span><span style="color: #007700">(-</span><span style="color: #0000BB">90</span><span style="color: #007700">, </span><span style="color: #0000BB">90</span><span style="color: #007700">, </span><span style="color: #0000BB">\Random\IntervalBoundary</span><span style="color: #007700">::</span><span style="color: #0000BB">ClosedClosed</span><span style="color: #007700">),<br />    </span><span style="color: #0000BB">$randomizer</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getFloat</span><span style="color: #007700">(-</span><span style="color: #0000BB">180</span><span style="color: #007700">, </span><span style="color: #0000BB">180</span><span style="color: #007700">, </span><span style="color: #0000BB">\Random\IntervalBoundary</span><span style="color: #007700">::</span><span style="color: #0000BB">OpenClosed</span><span style="color: #007700">),<br />);<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

   <div class="example-contents"><p>Das oben gezeigte Beispiel erzeugt
eine ähnliche Ausgabe wie:</p></div>
   <div class="example-contents screen">
<div class="annotation-interactive examplescode"><pre class="examplescode">Lat: +69.244304 Lng: -53.548951</pre>
</div>
   </div>
  </div>
 </div>


 <div class="refsect1 notes" id="refsect1-random-randomizer.getfloat-notes">
  <h3 class="title">Anmerkungen</h3>
  <blockquote class="note"><p><strong class="note">Hinweis</strong>: 
   <p class="para">
    This method implements the γ-section algorithm as published in
    <a href="https://dl.acm.org/doi/10.1145/3503512" class="link external">&raquo;&nbsp;
     Drawing Random Floating-Point Numbers from an Interval.
     Frédéric Goualard, ACM Trans. Model. Comput. Simul., 32:3, 2022
    </a>
    to obtain the desired behavioral properties.
   </p>
  </p></blockquote>
  <div class="caution"><strong class="caution">Achtung</strong>
   <p class="para">
    Underflow is intentionally left unhandled in the γ-section algorithm.
    This may result in incorrect values being returned for intervals with
    boundaries in the subnormal range of floating point numbers, i.e.
    for boundaries with an absolute value smaller than approximately
    <code class="literal">2<sup class="superscript">-1020</sup></code> (about <code class="literal">8.9e-308</code>).
   </p>
  </div>
 </div>


 <div class="refsect1 seealso" id="refsect1-random-randomizer.getfloat-seealso">
  <h3 class="title">Siehe auch</h3>
  <ul class="simplelist">
   <li><span class="methodname"><a href="random-randomizer.nextfloat.php" class="methodname" rel="rdfs-seeAlso">Random\Randomizer::nextFloat()</a> - Get a float from the right-open interval [0.0, 1.0)</span></li>
   <li><span class="methodname"><a href="random-randomizer.getint.php" class="methodname" rel="rdfs-seeAlso">Random\Randomizer::getInt()</a> - Get a uniformly selected integer</span></li>
  </ul>
 </div>


</div><?php manual_footer($setup); ?>