encoding - Mantissa Normalization of C# double -


edit: got work now, while normalizing mantiss important first set implicit bit, when decoding implicit bit not have added. left marked answer correct, information there helped.

i'm implementing encoding (distinguished encoding rules) , have slight problem encoding double values.

so, can out sign, exponent , mantissa double in c# using:

 // parts  double value = 10.0;  long bits = bitconverter.doubletoint64bits(value);  // note shift sign-extended, hence test against -1 not 1  bool negative = (bits < 0);  int exponent = (int)((bits >> 52) & 0x7ffl);  long mantissa = bits & 0xfffffffffffffl; 

(using code here). these values can encoded , simple reversal of process me original double.

however, der encoding rules specify mantissa should normalized:

in canonical encoding rules , distinguished encoding rules normalization specified , mantissa (unless 0) needs repeatedly shifted until least significant bit 1.

(see here in section 8.5.6.5).

doing hand using:

 while ((mantissa & 1) == 0)  {      mantissa >>= 1;      exponent++;  } 

will not work, , gives me strange values. (even when using whole function jon skeet posted in aforementioned link).

i seem missing here, easiest if first normalize mantiassa of double , "bits". however, can't see why normalization hand won't work correctly.

thanks help,

danny

edit: actual working problem showing issue mantiss normalization:

 static void main(string[] args)     {         console.writeline(calculatedouble(getbits(55.5, false)));          console.writeline(calculatedouble(getbits(55.5, true)));         console.readline();     }      private static double calculatedouble(tuple<bool, int, long> bits)     {         double result = 0;         bool isnegative = bits.item1;         int exponent = bits.item2;         long significand = bits.item3;          if (exponent == 2047 && significand != 0)         {             // special case         }         else if (exponent == 2047 && significand == 0)         {             result = isnegative ? double.negativeinfinity : double.positiveinfinity;         }         else if (exponent == 0)         {             // special case, subnormal numbers         }         else         {             /* old code, wont work double actualsignificand = significand*math.pow(2,                                   -52) + 1; */             double actualsignificand = significand*math.pow(2, -52);             int actualexponent = exponent - 1023;             if (isnegative)             {                 result = actualsignificand*math.pow(2, actualexponent);             }             else              {                 result = -actualsignificand*math.pow(2, actualexponent);**strong text**             }         }         return result;      }       private static tuple<bool, int, long> getbits(double d, bool normalizesignificand)     {         // translate double sign, exponent , mantissa.         long bits = bitconverter.doubletoint64bits(d);         // note shift sign-extended, hence test against -1 not 1         bool negative = (bits < 0);         int exponent = (int)((bits >> 52) & 0x7ffl);         long significand = bits & 0xfffffffffffffl;          if (significand == 0)         {             return tuple.create<bool, int, long>(false, 0, 0);         }         // fix: add implicit bit before normalization         if (exponent != 0)         {             significand = significand | (1l << 52);         }         if (normalizesignificand)         {             //* normalize */             while ((significand & 1) == 0)             {                 /*  i.e., mantissa */                 significand >>= 1;                 exponent++;             }         }         return tuple.create(negative, exponent, significand);      }     output:     55.5     2.25179981368527e+15 

when use bitconverter.doubletoint64bits, gives double value encoded in ieee 754 format. means significand encoded implicit leading bit. (“significand” preferred term fraction portion of floating-point value , used in ieee 754. significand linear. mantissa logarithmic. “mantissa” stems days when people had use logarithms , paper , tables of functions crude calculations.) recover unencoded significand, have restore implicit bit.

that not hard. once have separated sign bit, encoded exponent (as integer), , encoded significand (as integer), then, 64-bit binary floating-point:

  • if encoded exponent maximum (2047) , encoded significand non-zero, value nan. there additional information in significand whether nan signaling or not , other user- or implementation-defined information.
  • if encoded exponent maximum , encoded significand zero, value infinity (+ or – according sign).
  • if encoded exponent zero, implicit bit zero, actual significand encoded significand multiplied 2–52, , actual exponent 1 minus bias (1023) (so –1022).
  • otherwise, implicit bit one, actual significand encoded significand first multiplied 2–52 , added one, , actual exponent encoded exponent minus bias (1023).

(if want work integers , not have fractions significand, can omit multiplications 2–52 , add –52 exponent instead. in last case, significand added 252 instead of one.)

there alternative method avoids bitconverter , ieee-754 encoding. if can call frexp routine c#, return fraction , exponent mathematically instead of encodings. first, handle zeroes, infinities, , nans separately. use:

int exponent; double fraction = frexp(value, &exponent); 

this sets fraction value magnitude in [½, 1) , exponent such fraction•2exponent equals value. (note fraction still has sign; might want separate , use absolute value.)

at point, can scale fraction desired (and adjust exponent accordingly). scale odd integer, multiply 2 repeatedly until has no fractional part.


Comments

Popular posts from this blog

javascript - DIV "hiding" when changing dropdown value -

Does Firefox offer AppleScript support to get URL of windows? -

android - How to install packaged app on Firefox for mobile? -