vb.net中的IEEE754半精度(16位)浮点数据

时间:2016-01-22 17:09:15

标签: vb.net precision

VB.Net是否支持IEEE 754半精度(16位)浮点数据类型? 如果没有,是否有推荐的创建方式?

上下文:我最终通过COM通道向一个接受半精度值的设备发送字节流。我需要取用户输入的Decimal值并将其转换为两个字节的浮点数进行传输。我不确定在VB.Net中执行此操作的最佳方法

1 个答案:

答案 0 :(得分:1)

我与此库完全没有关联,但您可以使用this

这是一个在内部使用ushort成员的结构,它应该是您正在传输的内容。如果由于某种原因无法直接传输结构,则可以创建value字段public,然后使用它(或使用GetBytes()方法)。

我不确定转换的精确度,但你应该试验一下。

库是C#,但将它作为C#项目添加到您的解决方案并从Vb.Net使用它应该没有问题

更新

我花时间在Vb.net上制作了一个“安全”的最低版本。所有代码都来自该库,所有版权归他所有:

Public Class HalfPrecisionConverter
    Private Shared BaseTable As UShort() = GenerateBaseTable()
    Private Shared ShiftTable As SByte() = GenerateShiftTable()

    Private Shared Function GenerateBaseTable() As UShort()
        Dim intBaseTable = New UShort(511) {}
        For i = 0 To 255
            Dim e = CSByte(127 - i)
            If e > 24 Then
                ' Very small numbers map to zero
                intBaseTable(i Or &H0) = &H0
                intBaseTable(i Or &H100) = &H8000
            ElseIf e > 14 Then
                ' Small numbers map to denorms
                intBaseTable(i Or &H0) = CUShort(&H400 >> (18 + e))
                intBaseTable(i Or &H100) = CUShort((&H400 >> (18 + e)) Or &H8000)
            ElseIf e >= -15 Then
                ' Normal numbers just lose precision
                intBaseTable(i Or &H0) = CUShort((15 - e) << 10)
                intBaseTable(i Or &H100) = CUShort(((15 - e) << 10) Or &H8000)
            ElseIf e > -128 Then
                ' Large numbers map to Infinity
                intBaseTable(i Or &H0) = &H7c00
                intBaseTable(i Or &H100) = &Hfc00
            Else
                ' Infinity and NaN's stay Infinity and NaN's
                intBaseTable(i Or &H0) = &H7c00
                intBaseTable(i Or &H100) = &Hfc00
            End If
        Next

        Return intBaseTable
    End Function

    Private Shared Function GenerateShiftTable() As SByte()
        Dim intShiftTable = New SByte(511) {}
        For i = 0 To 255
            Dim e = CSByte(127 - i)
            If e > 24 Then
                ' Very small numbers map to zero
                intShiftTable(i Or &H0) = 24
                intShiftTable(i Or &H100) = 24
            ElseIf e > 14 Then
                ' Small numbers map to denorms
                intShiftTable(i Or &H0) = CSByte(e - 1)
                intShiftTable(i Or &H100) = CSByte(e - 1)
            ElseIf e >= -15 Then
                ' Normal numbers just lose precision
                intShiftTable(i Or &H0) = 13
                intShiftTable(i Or &H100) = 13
            ElseIf e > -128 Then
                ' Large numbers map to Infinity
                intShiftTable(i Or &H0) = 24
                intShiftTable(i Or &H100) = 24
            Else
                ' Infinity and NaN's stay Infinity and NaN's
                intShiftTable(i Or &H0) = 13
                intShiftTable(i Or &H100) = 13
            End If
        Next

        Return intShiftTable
    End Function

    Public Shared Function SingleToHalf([single] As Single) As UShort
        Dim value As UInteger = BitConverter.ToUInt32(BitConverter.GetBytes([single]), 0)

        Dim result = CUShort(baseTable((value >> 23) And &H1ff) + ((value And &H7fffff) >> shiftTable(value >> 23)))
        Return result
    End Function
End Class

使用:

HalfPrecisionConverter.SingleToHalf(xx)

返回UShort,如果需要传输字节,可以使用BitConverter.GetBytes()

C#unsafe版本应该快一点,因为它不使用BitConverter并直接使用指针将单个转换为其字节的UInteger,但我不确定VB.NET允许任何类型的指针转​​换