- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
internal static double GetExtendedFromBytes(byte[] bytes)
        {
            /*
                1   15      1   63
                s   e       i 	f
                    The value v of the number is given by: 
                if 0 <= e < 32767, then v = (-1)s * 2(e-16383) * (i.f) 
                if e = 32767 and f = 0, then v = (-1)s * Inf 
                if e = 32767 and f <> 0, then v is a NaN
             */
            const int memSize = 10;
            if (bytes == null)
                throw new ArgumentNullException("bytes");
            if (bytes.Length != memSize)
                throw new ArgumentException("Must be " + memSize + " bytes", "bytes");
            int s = bytes[0] >> 7;
            int e = 0x7FFF & ((bytes[0] << 8) | bytes[1]);
            int i = bytes[2] >> 7;
            ulong f = (ulong)(0x7F & bytes[2]);
            for (int j = 3; j < memSize; j++)
            {
                f <<= 8;
                f |= bytes[j];
            }
            decimal df = (decimal)f / 10000000000000000000 /* 10^19 */; // число f в формате 0.f
            double v;
            if (0 <= e && e < 32767)
            {
                int pow = e - 16383;
                decimal c = (s == 0 ? 1 : -1) * (decimal)Math.Pow(2, pow);
                decimal dv = c * (i + df); // значение, полученное по формуле для x86 Extended Precision Format
                if (f != 0) // HACK при вычислении по формуле искомое значение не удается получить - исправляем
                {
                    const decimal mn = 0.0776627963145224192m; // magic number, при значениях отличных от 2^x возникает разница кратная этому значению
                    decimal delta = Math.Abs(dv - c);
                    decimal add = 0;
                    if (pow >= 4)
                        add = Math.Round(delta * 1.0842021724855044340074528009m); // еще magic number
                    else if (pow >= 2)
                        add = Math.Ceiling(delta);
                    else if (pow >= 0)
                        add = Math.Ceiling(delta * 10) / 10m;
                    else
                    {
                        decimal m = 10m * (decimal)Math.Pow(2, Math.Abs(pow));
                        add = Math.Ceiling(delta * m) / m;
                    }
                    if (dv > 0)
                        dv += add * mn;
                    else
                        dv -= add * mn;
                }
                v = (double)dv;
            }
            else if (e == 32767)
            {
                if (f == 0)
                    v = s == 0 ? double.PositiveInfinity : double.NegativeInfinity;
                else
                    v = double.NaN;
            }
            else
            {
                throw new ArgumentOutOfRangeException("bytes");
            }
            return v;
        }
                                     
        
            Местные индусы постарались. Перевод 80 bit floating point в double. Причём если прочитать спецификацию IEEE-754, то код займет 3-4 строчки с простыми битовыми операциями.