Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>As several others have poited out, fractions of 64 can be precicely represented by IEEE-floats. This means we can also convert to a fraction by moving and masking bits.</p> <p>This is not the place to explain all details of floating point representations, please refer to <a href="http://en.wikipedia.org/wiki/IEEE_754-1985" rel="nofollow noreferrer">wikipedia</a> for details.</p> <p>Briefly: a floating point number is stored as (sign)(exp)(frac) where sign is 1 bit, exp is 11 bits and frac is the fraction part (after 1.) and is 52 bits. This is enterpreted as the number:</p> <pre><code>(sign == 1 ? -1 : 1) * 1.(frac) * 2^(exp-1023) </code></pre> <p>Thus, we can get the 64th by moving the point accoring to the exponent and masking out the 6 bits after the point. In Java:</p> <pre><code>private static final long MANTISSA_FRAC_BITMAP = 0xfffffffffffffl; private static final long MANTISSA_IMPLICIT_PREFIX = 0x10000000000000l; private static final long DENOM_BITMAP = 0x3f; // 1/64 private static final long DENOM_LEN = 6; private static final int FRAC_LEN = 52; public String floatAsFrac64(double d) { long bitmap = Double.doubleToLongBits(d); long mantissa = bitmap &amp; MANTISSA_FRAC_BITMAP | MANTISSA_IMPLICIT_PREFIX; long exponent = ((bitmap &gt;&gt; FRAC_LEN) &amp; 0x7ff) - 1023; boolean negative = (bitmap &amp; (1l &lt;&lt; 63)) &gt; 0; // algorithm: // d is stored as SE(11)F(52), implicit "1." before F // move point to the right &lt;exponent&gt; bits to the right: if(exponent &gt; FRAC_LEN) System.out.println("warning: loosing precision, too high exponent"); int pointPlace = FRAC_LEN-(int)exponent; // get the whole part as the number left of the point: long whole = mantissa &gt;&gt; pointPlace; // get the frac part as the 6 first bits right of the point: long frac = (mantissa &gt;&gt; (pointPlace-DENOM_LEN)) &amp; DENOM_BITMAP; // if the last operation shifted 1s out to the right, we lost precision, check with // if any of these bits are set: if((mantissa &amp; ((MANTISSA_FRAC_BITMAP | MANTISSA_IMPLICIT_PREFIX) &gt;&gt; (pointPlace - DENOM_LEN))) &gt; 0) { System.out.println("warning: precision of input is smaller than 1/64"); } if(frac == 0) return String.format("%d", whole); int denom = 64; // test last bit, divide nom and demon by 1 if not 1 while((frac &amp; 1) == 0) { frac = frac &gt;&gt; 1; denom = denom &gt;&gt; 1; } return String.format("%d %d/%d", whole, frac, denom); } </code></pre> <p>(this code can probably be made shorter, but reading bit-flipping-code like this is hard enough as it is...)</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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