2010-03-29 241 views
4

我發現了以下問題Convert Delphi Real48 to C# double但我想用另一種方式將C#轉換爲Delphi。將C#雙轉換爲Delphi Real48

有誰知道這可以做到嗎?我試過對代碼進行逆向工程,但沒有多少運氣。

更新:

後的C#代碼,將採取雙重並將其轉換成Real48(字節[大小6])我。

感謝

+0

什麼是轉換的語言 - Delphi或C#? – kludg 2010-03-29 15:56:33

+1

如果是Delphi,解決方案是「MyReal48Var:= MyDoubleVar;」 ;-) – 2010-03-29 18:20:43

回答

1

如果你熟悉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; 

} 
+0

@Seidr我不明白你發佈的代碼,它從哪裏獲取返回值,以及如何在開始時使用值填充d.a?謝謝 – lancscoder 2010-03-31 13:31:56

+0

從我可以看到 - 'da'變量是從輸入double派生的值的數組(我猜想的內存位數)。對於這個函數的第二個參數,你提供了一個POINTER到你在調用這個函數之前定義的「真實」變量。輸出然後直接輸出到該變量中。 正如我所說,這是一個C函數,所以需要修改才能使它在C#中工作。我純粹把它作爲一個正確的方向。你不明白C#對指針的支持。 祝您好運 – Seidr 2010-03-31 14:16:51

1

最簡單的方法,如果可能的話,將其轉換爲字符串,傳球,然後將其轉換回一個Real48

5

我碰到這個線程找相同的代碼。下面是我寫的東西:

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類似,因爲尾數是相同的。移位是將Mantissa置於正確位置所必需的。

Real48指數爲129偏置和雙具有負標誌被存儲在最後一個字節的第一位1023

偏差。

評論: 我不認爲這個代碼將工作在一個大的endian機器上。它不檢查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); 
} 
0
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; 
} 
+0

從此stdcall dll通常real48 6個字節被視爲8個字節。 因此,我們甚至不能發送Long Long轉換類型。 適當改變稱爲函數原型。 – 2014-02-22 09:07:14

+0

'unsigned long long Double_Real48(double d){unsigned long long r48 = 0,...... return r48; } ' – 2014-02-22 09:08:40

0

在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; 
}