将字节转换为扩展精度浮点不够准确

时间:2019-03-12 20:41:20

标签: vb.net binary

我有一些需要挖掘数据的旧文件。这些文件是由Lotus123 Release 4 for DOS创建的。我试图通过解析字节而不是使用Lotus打开文件来更快地读取文件。我有每个10字节的值记录。他们是80 bit Extended Precision Floating Point

Debug.Print(ConvertLongDouble80(New Byte() {0, 0, 0, 0, 0, 0, 0, 128, 255, 191}))                 ' Value = -1
Debug.Print(ConvertLongDouble80(New Byte() {205, 204, 204, 204, 204, 204, 204, 204, 251, 191}))    ' Value = -0.1
Debug.Print(ConvertLongDouble80(New Byte() {10, 215, 163, 112, 61, 10, 215, 163, 248, 191}))       ' Value = -0.01
Debug.Print(ConvertLongDouble80(New Byte() {59, 223, 79, 141, 151, 110, 18, 131, 245, 191}))       ' Value = -0.001
Debug.Print(ConvertLongDouble80(New Byte() {44, 101, 25, 226, 88, 23, 183, 209, 241, 191}))        ' Value = -0.0001
Debug.Print(ConvertLongDouble80(New Byte() {35, 132, 71, 27, 71, 172, 197, 167, 238, 191}))        ' Value = -0.00001
Debug.Print(ConvertLongDouble80(New Byte() {182, 105, 108, 175, 5, 189, 55, 134, 235, 191}))       ' Value = -0.000001
Debug.Print(ConvertLongDouble80(New Byte() {0, 0, 0, 0, 0, 0, 0, 128, 255, 63}))                   ' Value = 1
Debug.Print(ConvertLongDouble80(New Byte() {205, 204, 204, 204, 204, 204, 204, 204, 251, 63}))     ' Value = 0.1
Debug.Print(ConvertLongDouble80(New Byte() {10, 215, 163, 112, 61, 10, 215, 163, 248, 63}))       ' Value = 0.01
Debug.Print(ConvertLongDouble80(New Byte() {59, 223, 79, 141, 151, 110, 18, 131, 245, 63}))       ' Value = 0.001
Debug.Print(ConvertLongDouble80(New Byte() {44, 101, 25, 226, 88, 23, 183, 209, 241, 63}))        ' Value = 0.0001
Debug.Print(ConvertLongDouble80(New Byte() {35, 132, 71, 27, 71, 172, 197, 167, 238, 63}))        ' Value = 0.00001
Debug.Print(ConvertLongDouble80(New Byte() {182, 105, 108, 175, 5, 189, 55, 134, 235, 63}))       ' Value = 0.000001
Debug.Print(ConvertLongDouble80(New Byte() {188, 66, 122, 229, 213, 148, 191, 214, 231, 63}))     ' Value = 0.0000001

Function ConvertLongDouble80(ByVal TenBytes As Byte()) As Double
    'https://en.wikipedia.org/wiki/Extended_precision

    'get 15 bit exponent; remove the first bit which is the negative sign
    Dim arrExp As Byte() = New Byte() {TenBytes(8), (TenBytes(9) << 1) >> 1}
    Dim Expo As UInt16 = BitConverter.ToUInt16(arrExp, 0)

    'flag bits
    Dim Bit63 As UInt16 = Convert.ToUInt16(TenBytes(7) >> 7)
    Dim Bits63_62 As UInt16 = Convert.ToUInt16(TenBytes(7) >> 6)

    'fractional values
    TenBytes(7) = (TenBytes(7) << 1) >> 1
    Dim Bits62_0 As UInt64 = BitConverter.ToUInt64(TenBytes, 0)
    TenBytes(7) = (TenBytes(7) << 2) >> 2
    Dim Bits61_0 As UInt64 = BitConverter.ToUInt64(TenBytes, 0)

    If Bit63 = 0 and Bits62_0 = 0 Then
        Return 0
    Else
        Const ExponentBias As Integer = 16383
        Dim isNegative As Boolean = (TenBytes(9) And (1 << 7)) <> 0
        Dim NegVal As Int16 = IIf(isNegative, -1, 1)
        Dim expVal As Double = Math.Pow(2, Expo - ExponentBias)
        Dim LBits62 As Int16 = Len(CStr(Bits62_0))
        Dim mantissa As Double = CDbl("1." & CStr(Bits62_0))
        Dim result As Double = NegVal * expVal * mantissa
        Return result       
    End If

End Function
  

值-1转换为-1
  值-0.1转换为-0.09708764513821
  值-0.01转换为-0.00983011263306
  值-0.001转换为-0.00119273528211
  值-0.0001转换为-0.00009697388128
  值-0.00001转换为-0.00000981589215
  值-0.000001转换为-0.00000138095333
  值1转换为1
  值0.1转换为0.09708764513821
  值0.01转换为0.00983011263306
  值0.001转换为0.00119273528211
  值0.0001转换为0.00009697388128
  值0.00001转换为0.00000981589215
  值0.000001转换为0.00000138095333
  值0.0000001转换为0.00000009686278

我在做什么错。我的价值观还不够接近。我该如何解决?

0 个答案:

没有答案