将C#double转换为Delphi Real48

我发现以下问题将Delphi Real48转换为C#double,但我想转向其他方式,C#转向Delphi。

有谁知道如何做到这一点? 我试过逆向工程代码,但没有太多运气。

更新:

我正在使用C#代码,它将采用double并将其转换为Real48(大小为6的byte [])。

谢谢

我遇到了这个寻找相同代码的线程。 这是我最后写的:

public static byte [] Double2Real48(double d) { byte [] r48 = new byte[6]; byte [] da = BitConverter.GetBytes(d); for (int i = 0; i < r48.Length; i++) r48[i] = 0; //Copy the negative flag r48[5] |= (byte)(da[7] & 0x80); //Get the expoent byte b1 = (byte)(da[7] & 0x7f); ushort n = (ushort)(b1 << 4); byte b2 = (byte)(da[6] & 0xf0); b2 >>= 4; n |= b2; if (n == 0) return r48; byte ex = (byte)(n - 1023); r48[0] = (byte)(ex + 129); //Copy the Mantissa r48[5] |= (byte)((da[6] & 0x0f) << 3);//Get the last four bits r48[5] |= (byte)((da[5] & 0xe0) >> 5);//Get the first three bits r48[4] = (byte)((da[5] & 0x1f) << 3);//Get the last 5 bits r48[4] |= (byte)((da[4] & 0xe0) >> 5);//Get the first three bits r48[3] = (byte)((da[4] & 0x1f) << 3);//Get the last 5 bits r48[3] |= (byte)((da[3] & 0xe0) >> 5);//Get the first three bits r48[2] = (byte)((da[3] & 0x1f) << 3);//Get the last 5 bits r48[2] |= (byte)((da[2] & 0xe0) >> 5);//Get the first three bits r48[1] = (byte)((da[2] & 0x1f) << 3);//Get the last 5 bits r48[1] |= (byte)((da[1] & 0xe0) >> 5);//Get the first three bits return r48; } 

Real48类似于IEEE 754,因为尾数将是相同的。 位移是必要的,以使尾数位于正确的位置。

Real48指数的偏差为129,双精度的偏差为1023。

负标志存储在最后一个字节的第一位。

注意:我认为此代码不适用于大端机器。 它不检查NAN或INF。

这是将real48转换为double的代码。 它是从Free Pascal编译器移植的:

 static double real2double(byte [] r) { byte [] res = new byte[8]; int exponent; //Return zero if the exponent is zero if (r[0] == 0) return (double)0; //Copy Mantissa res[0] = 0; res[1] = (byte)(r[1] << 5); res[2] = (byte)((r[1] >> 3) | (r[2] << 5)); res[3] = (byte)((r[2] >> 3) | (r[3] << 5)); res[4] = (byte)((r[3] >> 3) | (r[4] << 5)); res[5] = (byte)((r[4] >> 3) | ((r[5] & 0x7f) << 5)); res[6] = (byte)((r[5] & 0x7f) >> 3); //Copy exponent //correct exponent exponent = (r[0] + (1023-129)); res[6] = (byte)(res[6] | ((exponent & 0xf) << 4)); res[7] = (byte)(exponent >> 4); //Set Sign res[7] = (byte)(res[7] | (r[5] & 0x80)); return BitConverter.ToDouble(res, 0); } 

如果您熟悉C(因为您使用C#编写应该没问题),请查看此函数。 将它移到C#应该不会太困难。

这是相当丑陋的,但我想的是必要的。

参考: http : //forums.ni.com/ni/board/message?board.id = 60&message.id = 3553

  enum prconverr double_to_real (double d, real *r) /* converts C double to Pascal real, returns error code */ { union doublearray da; unsigned x; da.d = d; /* check for 0.0 */ if ((da.a[0] == 0x0000) && (da.a[1] == 0x0000) && (da.a[2] == 0x0000) && /* ignore sign bit */ ((da.a[3] & 0x7FFF) == 0x0000)) { /* exponent and significand are both 0, so value is 0.0 */ (*r)[2] = (*r)[1] = (*r)[0] = 0x0000; /* sign bit is ignored ( -0.0 -> 0.0 ) */ return prOK; } /* test for maximum exponent value */ if ((da.a[3] & 0x7FF0) == 0x7FF0) { /* value is either Inf or NaN */ if ((da.a[0] == 0x0000) && (da.a[1] == 0x0000) && (da.a[2] == 0x0000) && ((da.a[3] & 0x000F) == 0x0000)) { /* significand is 0, so value is Inf */ /* value becomes signed maximum real, */ /* and error code prInf is returned */ (*r)[1] = (*r)[0] = 0xFFFF; (*r)[2] = 0x7FFF | (da.a[3] & 0x8000); /* retain sign bit */ return prInf; } else { /* significand is not 0, so value is NaN */ /* value becomes 0.0, and prNaN code is returned */ /* sign bit is ignored (no negative NaN) */ (*r)[2] = (*r)[1] = (*r)[0] = 0x0000; /* sign bit is ignored ( -NaN -> +NaN ) */ return prNaN; } } /* round significand if necessary */ if ((da.a[0] & 0x1000) == 0x1000) { /* significand's 40th bit set, so round significand up */ if ((da.a[0] & 0xE000) != 0xE000) /* room to increment 3 most significant bits */ da.a[0] += 0x2000; else { /* carry bit to next element */ da.a[0] = 0x0000; /* carry from 0th to 1st element */ if (da.a[1] != 0xFFFF) da.a[1]++; else { da.a[1] = 0x0000; /* carry from 1st to 2nd element */ if (da.a[2] != 0xFFFF) da.a[2]++; else { da.a[2] = 0x0000; /* carry from 2nd to 3rd element */ /* significand may overflow into exponent */ /* exponent not full, so won't overflow */ da.a[3]++; } } } } /* get exponent for underflow/overflow tests */ x = (da.a[3] & 0x7FF0) >> 4; /* test for underflow */ if (x < 895) { /* value is below real range */ (*r)[2] = (*r)[1] = (*r)[0] = 0x0000; if ((da.a[3] & 0x8000) == 0x8000) /* sign bit was set, so value was negative */ return prNegUnderflow; else /* sign bit was not set */ return prPosUnderflow; } /* test for overflow */ if (x > 1149) { /* value is above real range */ (*r)[1] = (*r)[0] = 0xFFFF; (*r)[2] = 0x7FFF | (da.a[3] & 0x8000); /* retain sign bit */ return prOverflow; } /* value is within real range */ (*r)[0] = (x - 894) | /* re-bias exponent */ ((da.a[0] & 0xE000) >> 5) | /* begin significand */ (da.a[1] << 11); (*r)[1] = (da.a[1] >> 5) | (da.a[2] << 11); (*r)[2] = (da.a[2] >> 5) | ((da.a[3] & 0x000F) << 11) | (da.a[3] & 0x8000); /* copy sign bit */ return prOK; } 

如果可能,最简单的方法是将其转换为字符串,传递,然后将其转换回Real48

 double Double_Real48(double d) { unsigned long long r48 = 0, tmp; tmp = *(long long *)&d;//m tmp/=0x20; tmp&=0x7FFFFFFFFF00; r48+=tmp; tmp = *(long long *)&d;//e tmp/=0x10000000000000; tmp-=894; tmp&=0xFF; if (tmp == 0) return 0.0; r48+=tmp; tmp = *(long long *)&d;//s tmp/=0x10000; tmp&=0x800000000000; r48+=tmp; return *(double *)&r48; } double Real48_Double(double r48) { unsigned long long d = 0, tmp; tmp= *(long long *)&r48;//m tmp&=0x7FFFFFFFFF00; tmp*=0x20; d+=tmp; tmp= *(long long *)&r48;//e tmp&=0xFF; if (tmp == 0) return 0.0; tmp+=894; tmp*=0x10000000000000; d+=tmp; tmp= *(long long *)&r48;//s tmp&=0x800000000000; tmp*=0x10000; d+=tmp; return *(double *)&d; } 

在C / C ++中

 typedef struct { unsigned char exponent; // 8 bites; unsigned long mantisaLo; // 32 of 39 bites unsigned char mantisaHi : 7, sign : 1; // 7 of 39 bites } T_Real48; typedef struct { unsigned long mantisaLo; // 32 of 52 bites unsigned long mantisaHi:20, exponent: 11, sign : 1; // 20 of 52 bites } T_Double64; double doubleToReal48(double val) { T_Real48 real48; T_Double64 *double64 = (T_Double64*) &val; real48.mantisaHi = double64->mantisaHi >> 13; real48.mantisaLo =(double64->mantisaLo >> 13) + ((double64->mantisaHi & 0x1FFF) << 19); real48.exponent = double64->exponent - 894; real48.sign = double64->sign; if (real48.exponent == 0) { real48.mantisaHi = 0; real48.mantisaLo = 0; } return *(double *)&real48; } double real48ToDouble(double val) { T_Real48 *real48 = (T_Real48*) &val; T_Double64 double64; double64.mantisaHi = (real48->mantisaHi << 13) + (real48->mantisaLo >> 19); double64.mantisaLo = real48->mantisaLo << 13; double64.exponent = real48->exponent + 894; double64.sign = real48->sign; return *(double *)&double64; }