1 bit-manipulation ieee-754 mbf
我在下面找到了将MBF转换为IEEE的主题.
任何人都可以解释下面标记的代码的功能是什么?
昏暗的标志As Byte = mbf(6)和ToByte(&H80) '是什么原因和(&H80)?
Dim exp As Int16 = mbf(7) - 128S - 1S + 1023S '为什么是1152(128 + 1 + 1023)?
ieee(7)= ieee(7)或签署 '为什么不将标志保存到ieee(7)?
ieee(7)= ieee(7)或ToByte(exp >> 4 And&HFF)'换班4的原因是什么?
Public Shared Function MTID(ByVal src() As Byte, ByVal startIndex As Integer) As Double
Dim mbf(7) As Byte
Dim ieee(7) As Byte
Array.Copy(src, startIndex, mbf, 0, 8)
If mbf(7) <> 0 Then
Dim sign As Byte = mbf(6) And ToByte(&H80)
Dim exp As Int16 = mbf(7) - 128S - 1S + 1023S
ieee(7) = ieee(7) Or sign
ieee(7) = ieee(7) Or ToByte(exp >> 4 And &HFF)
ieee(6) = ieee(6) Or ToByte(exp << 4 And &HFF)
For i As Integer = 6 To 1 Step -1
mbf(i) <<= 1
mbf(i) = mbf(i) Or mbf(i - 1) >> 7
Next
mbf(0) <<= 1
For i As Integer = 6 To 1 Step -1
ieee(i) = ieee(i) Or mbf(i) >> 4
ieee(i - 1) = ieee(i - 1) Or mbf(i) << 4
Next
ieee(0) = ieee(0) Or mbf(0) >> 4
End If
Return BitConverter.ToDouble(ieee, 0)
End Function
Run Code Online (Sandbox Code Playgroud)
IEEE754双格式由1位符号,11位指数和52位尾数组成:
7 6 5 4 3 2 1 0
seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
Run Code Online (Sandbox Code Playgroud)
由于字节序的变幻莫测,左边最重要的字节实际上ieee(7),右边最不重要的是ieee(0)- 这对于mbf()下面是相同的.
指数给出一个值0through 2047(2 11 -1),其中一些用于表示特殊值,如+/-inf(无穷大)和nan(不是数字).
尾数位表示,从左至右,1/2,1/4,1/8等等.为了得到这个数,你计算n =( - 1)s x 2 e-bias x 1.m
Microsoft双二进制格式是:
7 6 5 4 3 2 1 0
eeeeeeee smmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
Run Code Online (Sandbox Code Playgroud)
您看到的代码只是将值从MBF传输(并稍微改变)为IEEE754双精度格式.
回答您的具体问题:
Dim sign As Byte = mbf(6) And ToByte(&H80)
'And&H80'的原因是什么?
Hex 80(&H80)是二进制模式1000 0000.
当你得到AND一个值时,&H80如果设置了该位,则得到0.
这基本上只记录了数字的符号,你可以简单地将它原样转移mbf(6)到ieee(7).
Dim exp As Int16 = mbf(7) - 128S - 1S + 1023S
为什么选择1152(128 + 1 + 1023)?
IEEE754中的指数是有偏见的指数.换句话说,存储的值可以是0直通的,255但是由这些值表示的实际值可以是-128直通127(现在忽略特殊值).
这允许您为非常小的值指定负指数,为大值指定正指数.
MBF指数也有偏见,但它们128对单一和双重类型都有偏见,而IEEE754双精度指数则有0点1023.
额外的原因-1是因为MBF和IEEE754之间的区别在于隐含1的位置.IEEE754将其置于二进制点之前,MBF之后.这意味着指数必须调整为1.
ieee(7) = ieee(7) Or sign
为什么我们不将标志保存到ieee(7)?
这是一个轻微的谜,因为ieee(7)在那一点上没有明确设定.我只能假设ieee()在创建时已经初始化为零,否则你可能会遇到麻烦,因为这里几乎所有的传输操作都是用OR.
你是对的,只是使用它更有意义ieee(7) = sign.OR组合指数位的实际结果在下一行.
ieee(7) = ieee(7) Or ToByte(exp >> 4 And &HFF)
换班4的原因是什么?
因为IEEE754指数跨越两个字节,并且您只希望那个指数的一部分位于最重要的指数中.指数的七位进入最高有效字节,另外四位进入下一个字节.
这由两行处理:
ieee(7) = ieee(7) Or ToByte(exp >> 4 And &HFF) ' upper 7 bits '
ieee(6) = ieee(6) Or ToByte(exp << 4 And &HFF) ' lower 4 bits '
Run Code Online (Sandbox Code Playgroud)
给定16位值00000abcdefghijk,计算两者:
>> 4 and &hff : 0abcdefg (s will go at the left)
<< 4 and &hff : hijk0000 (m will go at the right)
Run Code Online (Sandbox Code Playgroud)