vb.net 中的 IEEE754 半精度(16 位)浮点数据
IEEE754 Half Precision (16 bit) floating point data in vb.net
VB.Net是否支持 IEEE 754 半精度(16 位)浮点数据类型?
如果没有,是否有推荐的创建方法?
上下文:我最终通过 COM 通道将字节流发送到接受半精度值的设备。我需要将用户输入的 Decimal
值转换为两个字节的浮点数进行传输。我不确定在 VB.Net
中执行此操作的最佳方法
我与这个库完全没有关联,但你可以使用 this。
它是一个内部使用 ushort
成员的结构,这应该是您要传输的内容。如果由于某种原因你不能直接传输结构,你可以只制作 value
字段 public
,然后使用它(或使用 GetBytes()
方法)。
不过我不确定转换的精度,您应该试验一下。
该库是 C#,但将它作为 C# 项目添加到您的解决方案并从 Vb.Net
使用它应该没有问题
更新
我花时间在 Vb.net 中制作了一个 "safe" 最低版本。所有代码均来自该库,所有版权归他所有:
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)
就是returns一个UShort
,如果需要字节数传输,可以用BitConverter.GetBytes()
C# 不安全版本应该快一点,因为它不使用 BitConverter
而是直接使用指针将单个字节转换为 UInteger
个字节,但我不确定 VB.NET 允许任何类型的指针转换
VB.Net是否支持 IEEE 754 半精度(16 位)浮点数据类型? 如果没有,是否有推荐的创建方法?
上下文:我最终通过 COM 通道将字节流发送到接受半精度值的设备。我需要将用户输入的 Decimal
值转换为两个字节的浮点数进行传输。我不确定在 VB.Net
我与这个库完全没有关联,但你可以使用 this。
它是一个内部使用 ushort
成员的结构,这应该是您要传输的内容。如果由于某种原因你不能直接传输结构,你可以只制作 value
字段 public
,然后使用它(或使用 GetBytes()
方法)。
不过我不确定转换的精度,您应该试验一下。
该库是 C#,但将它作为 C# 项目添加到您的解决方案并从 Vb.Net
使用它应该没有问题更新
我花时间在 Vb.net 中制作了一个 "safe" 最低版本。所有代码均来自该库,所有版权归他所有:
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)
就是returns一个UShort
,如果需要字节数传输,可以用BitConverter.GetBytes()
C# 不安全版本应该快一点,因为它不使用 BitConverter
而是直接使用指针将单个字节转换为 UInteger
个字节,但我不确定 VB.NET 允许任何类型的指针转换