title: Closest integer to floating-point value in C++03
body: <p>For some integer type, how can I find the value that is closest to some value of a floating-point type even when the floating point value is far outside the representable range of the integer.</p>
  
  <p>Or more precisely:</p>
  
  <p>Let <code>F</code> be a floating-point type (probably <code>float</code>, <code>double</code>, or <code>long double</code>).
  Let <code>I</code> be an integer type.</p>
  
  <p>Assume that both <code>F</code> and <code>I</code> have valid specializations of <code>std::numeric_limits&lt;&gt;</code>.</p>
  
  <p>Given a representable value of <code>F</code>, and using only C++03, how can I find the closest representable value of <code>I</code>?</p>
  
  <p>I am after in a pure, efficient, and thread-safe solution, and one that assumes nothing about the platform except what is guaranteed by C++03.</p>
  
  <p>If such an solution does not exist, is it possible to find one using the new features of C99/C++11?</p>
  
  <p>Using <code>lround()</code> of C99 seems to be problematic due to the non-trivial way in which domain errors are reported. Can these domain errors be caught in a portable and thread-safe way?</p>
  
  <p>Note: I am aware that Boost probably offers a solution via its <code>boost::numerics::converter&lt;&gt;</code> template, but due to its high complexity and verbosity, and I have not been able to extract the essentials from it, and therefore I have not been able to check whether their solution makes assumptions beyond C++03.</p>
  
  <p>The following naive approach fails due to the fact that the result of <code>I(f)</code> is undefined by C++03 when the integral part of <code>f</code> is not a representable value of <code>I</code>.</p>
  
  <pre><code>template&lt;class I, class F&gt; I closest_int(F f)
  {
    return I(f);
  }
  </code></pre>
  
  <p>Consider then the following approach:</p>
  
  <pre><code>template&lt;class I, class F&gt; I closest_int(F f)
  {
    if (f &lt; std::numeric_limits&lt;I&gt;::min()) return std::numeric_limits&lt;I&gt;::min();
    if (std::numeric_limits&lt;I&gt;::max() &lt; f) return std::numeric_limits&lt;I&gt;::max();
    return I(f);
  }
  </code></pre>
  
  <p>This also fails because the integral parts of <code>F(std::numeric_limits&lt;I&gt;::min())</code> and <code>F(std::numeric_limits&lt;I&gt;::max())</code> may still not be representable in <code>I</code>.</p>
  
  <p>Finally consider this third approach which also fails:</p>
  
  <pre><code>template&lt;class I, class F&gt; I closest_int(F f)
  {
    if (f &lt;= std::numeric_limits&lt;I&gt;::min()) return std::numeric_limits&lt;I&gt;::min();
    if (std::numeric_limits&lt;I&gt;::max() &lt;= f) return std::numeric_limits&lt;I&gt;::max();
    return I(f);
  }
  </code></pre>
  
  <p>This time <code>I(f)</code> will always have a well-defined result, however, since <code>F(std::numeric_limits&lt;I&gt;::max())</code> may be much smaller than <code>std::numeric_limits&lt;I&gt;::max()</code>, it is possible that we will return <code>std::numeric_limits&lt;I&gt;::max()</code> for a floating-point value that is multiple integer values below <code>std::numeric_limits&lt;I&gt;::max()</code>.</p>
  
  <p>Note that all the trouble arises because it is undefined whether the conversion <code>F(i)</code> rounds up, or down to the closest representable floating-point value.</p>
  
  <p>Here is the relevant section from C++03 (4.9 Floating-integral conversions):</p>
  
  <blockquote>
    <p>An rvalue of an integer type or of an enumeration type can be converted to an rvalue of a floating point
    type. The result is exact if possible. Otherwise, it is an implementation-defined choice of either the next
    lower or higher representable value.</p>
  </blockquote>