VB.Net是否支持IEEE 754半精度(16位)浮点数据类型? 如果没有,是否有推荐的创建方式?
上下文:我最终通过COM通道向一个接受半精度值的设备发送字节流。我需要取用户输入的Decimal
值并将其转换为两个字节的浮点数进行传输。我不确定在VB.Net中执行此操作的最佳方法
答案 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允许任何类型的指针转换