0

我正在尝试为半精度浮点类型实现binary16 编码。

除了一个细节之外,该代码正在工作:它返回一个具有三个属性(符号、指数、分数)的对象,但我希望它返回浮点数。现在,我必须打电话to_f才能到达花车。我希望它能够像集成的 int 和 float 类一样工作。

这是我的代码:

require 'bindata'
class Binary16Be < BinData::Record
  # naming based on https://en.wikipedia.org/wiki/Half-precision_floating-point_format
  bit1 :sign_bit
  bit5 :exponent
  bit10 :fraction

  def sign
    sign_bit.zero? ? 1 : -1
  end

  def to_f
    if exponent == 31 # special value in binary16 - all exponent bits are 1
      return fraction.zero? ? (sign * Float::INFINITY) : Float::NAN
    end
    sign * 2**(exponent - 15) * (1.0 + fraction.to_f / 1024)
  end
end

我想要什么:

Binary16Be.read("\x3C\x00")
=> 1.0

现在发生了什么:

Binary16Be.read("\x3C\x00")
{:sign_bit=>0, :exponent=>15, :fraction=>0}
4

1 回答 1

0

(这实际上不是我自己的答案,我是从 gem 的作者那里收到的。对他的答案稍作改动,以更好地适应这种问答格式。)

该过程在 bindata Wiki / Primitive Types 中进行了描述

在你的情况下:

  1. 子类Primitive而不是Record
  2. 重命名#to_f#get
  3. 实施#set

转换后的代码

class Binary16Be < BinData::Primitive
  # naming based on
  # https://en.wikipedia.org/wiki/Half-precision_floating-point_format
  bit1 :sign_bit
  bit5 :exponent
  bit10 :fraction

  def sign
    sign_bit.zero? ? 1 : -1
  end

  def get
    if exponent == 31 # special value in binary16 - all exponent bits are 1
      return fraction.zero? ? (sign * Float::INFINITY) : Float::NAN
    end
    sign * 2**(exponent - 15) * (1.0 + fraction.to_f / 1024)
  end

  def set(val)
    self.sign = (val >= 0.0)
    self.fraction = ... # TODO implement
    self.exponent = ... # TODO implement
  end
end
于 2017-04-07T18:54:47.237 回答