2015-06-23 66 views
0

下面的代码很简单,将32位整数从传递的对象转换为函数,32位整数表示浮点数。我已经用在线计算器检查过,我得到的符号,指数和mantessa正确的方式,但奇怪的是我得到的答案错了。IEEE754到浮点C#

任何人都可以请检查,如果我是数学(或可能编程)做错了莫名其妙?!

问候

public double FromFloatSafe(object f) 
    { 
     uint fb = Convert.ToUInt32(f); 


     uint sign, exponent = 0, mantessa = 0; 
     uint bias = 127; 

     sign = (fb >> 31) & 1; 
     exponent = (fb >> 23) & 0xFF; 
     mantessa = (fb & 0x7FFFFF); 
     double fSign = Math.Pow((-1), sign); 
     double fMantessa = 1 + (1/mantessa); 
     double fExponent = Math.Pow(2, (exponent -bias)); 
     double ret = fSign * fMantessa * fExponent; 
     return ret; 
    } 
+3

'BitConverter.GetBytes(FB)和'那么'BitConverter.ToSingle()'? –

+1

使用'Math.Pow'作为fSign有点夸张:-)'sign == 0? 1:-1'。这是尾数,而不是mantessa。 – xanatos

+0

为什么您将浮点数作为整数传递?你究竟在做什么? C#可以处理强制转换,您为什么使用错误的数据类型? – Luaan

回答

2

类似的东西:

uint fb = Convert.ToUInt32(f); 

    return BitConverter.ToSingle(BitConverter.GetBytes((int) fb), 0); 
+0

谢谢你是我正在寻找的正确答案! – Combinu

0

这种处理甚至非正规编号:

public static float FromFloatSafe(object f) 
{ 
    uint fb = Convert.ToUInt32(f); 

    int sign = (int)((fb >> 31) & 1); 
    int exponent = (int)((fb >> 23) & 0xFF); 
    int mantissa = (int)(fb & 0x7FFFFF); 

    float fMantissa; 
    float fSign = sign == 0 ? 1.0f : -1.0f; 

    if (exponent != 0) 
    { 
     exponent -= 127; 
     fMantissa = 1.0f + (mantissa/(float)0x800000); 
    } 
    else 
    { 
     if (mantissa != 0) 
     { 
      // denormal 
      exponent -= 126; 
      fMantissa = 1.0f/(float)0x800000; 
     } 
     else 
     { 
      // +0 and -0 cases 
      fMantissa = 0; 
     } 
    } 

    float fExponent = (float)Math.Pow(2.0, exponent); 
    float ret = fSign * fMantissa * fExponent; 
    return ret; 
} 

请注意,我觉得有什么可疑这里,但你要求它,我写了它 ...我觉得这是一个XY problem

啊......并指出,虽然在学术上我写的很有意思,我通常做这种方式:

[StructLayout(LayoutKind.Explicit)] 
public struct UInt32ToFloat 
{ 
    [FieldOffset(0)] 
    public uint UInt32; 

    [FieldOffset(0)] 
    public float Single; 
} 

然后

float f = new UInt32ToFloat { UInt32 = Convert.ToUInt32(f) }.Single; 
+0

注意:'struct' /'[FieldOffset]'是一个很好的选择(不计算) - 但只适用于两种位长相同的类型(在这种情况下,uint/float为32位) – joe

+0

@joe你甚至可以使用如果你想...(或Int64的4x'Int16),它可以分割Int64的高位/低位Int32。 – xanatos

+0

确实如此,但我的意思是将Int16转换为double。由于符号不会以这种方式工作。 – joe