Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You have to define a format, and implement that. Typically, most of the network protocols I know use IEEE float and double, output big-endian (but other formats are possible). The advantage of using IEEE formats is that it is what most of the current everyday machines use internally; if you're on one of these machines (and portability of your code to other machines, like mainframes, isn't an issue), you can "convert" to the format simply by type-punning to an unsigned int of the same size, and outputting that. So, for example, you might have: </p> <pre><code>obstream&amp; operator&lt;&lt;( obstream&amp; dest, uint64_t value ) { dest.put((value &gt;&gt; 56) &amp; 0xFF); dest.put((value &gt;&gt; 48) &amp; 0xFF); dest.put((value &gt;&gt; 40) &amp; 0xFF); dest.put((value &gt;&gt; 32) &amp; 0xFF); dest.put((value &gt;&gt; 24) &amp; 0xFF); dest.put((value &gt;&gt; 16) &amp; 0xFF); dest.put((value &gt;&gt; 8) &amp; 0xFF); dest.put((value ) &amp; 0xFF); return dest; } obstream&amp; operator&lt;&lt;( obstream&amp; dest, double value ) { return dest &lt;&lt; reinterpret_cast&lt;uint64_t const&amp;&gt;( value ); } </code></pre> <p>If you have to be portable to a machine not supporting IEEE (e.g. any of the modern mainframes), you'll need something a bit more complicated:</p> <pre><code>obstream&amp; obstream::operator&lt;&lt;( obstream&amp; dest, double value ) { bool isNeg = value &lt; 0; if ( isNeg ) { value = - value; } int exp; if ( value == 0.0 ) { exp = 0; } else { value = ldexp( frexp( value, &amp;exp ), 53 ); exp += 1022; } uint64_t mant = static_cast&lt; uint64_t &gt;( value ); dest.put( (isNeg ? 0x80 : 0x00) | exp &gt;&gt; 4 ); dest.put( ((exp &lt;&lt; 4) &amp; 0xF0) | ((mant &gt;&gt; 48) &amp; 0x0F) ); dest.put( mant &gt;&gt; 40 ); dest.put( mant &gt;&gt; 32 ); dest.put( mant &gt;&gt; 24 ); dest.put( mant &gt;&gt; 16 ); dest.put( mant &gt;&gt; 8 ); dest.put( mant ); return dest; } </code></pre> <p>(Note that this doesn't handle NaN's and infinities correctly. Personally, I would ban them from the format, since not all floating point representations support them. But then, there's no floating point format on an IBM mainframe which will support 1E306, either, although you can encode it in the IEEE double format above.)</p> <p>Reading is, of course, the opposite. Either:</p> <pre><code>ibstream&amp; operator&gt;&gt;( ibstream&amp; source, uint64_t&amp; results ) { uint64_t value = (source.get() &amp; 0xFF) &lt;&lt; 56; value |= (source.get() &amp; 0xFF) &lt;&lt; 48; value |= (source.get() &amp; 0xFF) &lt;&lt; 40; value |= (source.get() &amp; 0xFF) &lt;&lt; 32; value |= (source.get() &amp; 0xFF) &lt;&lt; 24; value |= (source.get() &amp; 0xFF) &lt;&lt; 16; value |= (source.get() &amp; 0xFF) &lt;&lt; 8; value |= (source.get() &amp; 0xFF) ; if ( source ) results = value; return source; } ibstream&amp; operator&gt;&gt;( ibstream&amp; source, double&amp; results) { uint64_t tmp; source &gt;&gt; tmp; if ( source ) results = reinterpret_cast&lt;double const&amp;&gt;( tmp ); return source; } </code></pre> <p>or if you can't count on IEEE:</p> <pre><code>ibstream&amp; ibstream::operator&gt;&gt;( ibstream&amp; source, double&amp; results ) { uint64_t tmp; source &gt;&gt; tmp; if ( source ) { double f = 0.0; if ( (tmp &amp; 0x7FFFFFFFFFFFFFFF) != 0 ) { f = ldexp( ((tmp &amp; 0x000FFFFFFFFFFFFF) | 0x0010000000000000), static_cast&lt;int&gt;( (tmp &amp; 0x7FF0000000000000) &gt;&gt; 52 ) - 1022 - 53 ); } if ( (tmp &amp; 0x8000000000000000) != 0 ) { f = -f; } dest = f; } return source; } </code></pre> <p>(This assumes that the input is not an NaN or an infinity.)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload