将无符号16位浮点数编码为二进制。

huangapple go评论106阅读模式
英文:

go - encoding unsigned 16 bit float in binary

问题

在Go语言中,你可以如何将一个浮点数编码为一个字节数组,作为一个16位无符号浮点数,其中有11个显式位的尾数和5个显式位的指数?

似乎没有一种简洁的方法来实现这个。我唯一能想到的是按照 https://stackoverflow.com/questions/22491876/convert-byte-array-uint8-to-float64-in-golang 中的方法进行编码,然后手动截断位数。

是否有一种"Go"的方式来实现这个?

以下是精确的定义:

一个16位无符号浮点数,具有11个显式位的尾数和5个显式位的指数

该位格式松散地模拟了IEEE 754。例如,1微秒表示为0x1,它的指数为零,表示在5个高位比特中,尾数为1,表示在11个低位比特中。当显式指数大于零时,假定尾数中有一个隐式的高位第12位为1。例如,浮点值0x800的显式指数为1,尾数为0,但有效尾数为4096(假定第12位为1)。此外,实际指数比显式指数小1,并且该值表示4096微秒。任何大于可表示范围的值都将被截断为0xFFFF。

英文:

In Go, how can I encode a float into a byte array as a 16 bit unsigned float with 11 explicit bits of mantissa and 5 bits of explicit exponent?

There doesn't seem to be a clean way to do it. The only thing I can think of is encoding it as in https://stackoverflow.com/questions/22491876/convert-byte-array-uint8-to-float64-in-golang and manually truncating the bits.

Is there a "go" way to do this?

Here's the exact definition:
> A 16 bit unsigned float with 11 explicit bits of mantissa and 5 bits of explicit exponent
>
> The bit format is loosely modeled after IEEE 754. For example, 1 microsecond is represented as 0x1, which has an exponent of zero, presented in the 5 high order bits, and mantissa of 1, presented in the 11 low order bits. When the explicit exponent is greater than zero, an implicit high-order 12th bit of 1 is assumed in the mantissa. For example, a floatingvalue of 0x800 has an explicit exponent of 1, as well as an explicit mantissa of 0, but then has an effective mantissa of 4096 (12th bit is assumed to be 1). Additionally, the actual exponent is one-less than the explicit exponent, and the value represents 4096 microseconds. Any values larger than the representable range are clamped to 0xFFFF.

答案1

得分: 2

我不确定我是否正确理解了编码(请参见我对原始问题的评论),但是这里有一个函数可能可以实现你想要的功能:

func EncodeFloat(seconds float64) uint16 {
    us := math.Floor(1e6*seconds + 0.5)
    if us < 0 {
        panic("cannot encode negative value")
    } else if us > (1<<30)*4095+0.5 {
        return 0xffff
    }
    usInt := uint64(us)
    expBits := uint16(0)
    if usInt >= 2048 {
        exp := uint16(1)
        for usInt >= 4096 {
            exp++
            usInt >>= 1
        }
        usInt -= 2048
        expBits = exp << 11
    }
    return expBits | uint16(usInt)
}

(代码位于 http://play.golang.org/p/G599VOBMcL

英文:

I am not sure whether I understand the encoding correctly (see my comment on the original question), but here is a function which may do what you want:

func EncodeFloat(seconds float64) uint16 {
	us := math.Floor(1e6*seconds + 0.5)
	if us &lt; 0 {
		panic(&quot;cannot encode negative value&quot;)
	} else if us &gt; (1&lt;&lt;30)*4095+0.5 {
		return 0xffff
	}
	usInt := uint64(us)
	expBits := uint16(0)
	if usInt &gt;= 2048 {
		exp := uint16(1)
		for usInt &gt;= 4096 {
			exp++
			usInt &gt;&gt;= 1
		}
		usInt -= 2048
		expBits = exp &lt;&lt; 11
	}
	return expBits | uint16(usInt)
}

(code is at http://play.golang.org/p/G599VOBMcL )

huangapple
  • 本文由 发表于 2015年4月22日 14:38:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/29789610.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定