Float类型转half类型的实现

当float类型绝对值小于5.9604644e-8(0x33800000)时

当float值为5.9604644e-8(0x33800000),转换后的half值位5.97e-8(0x0001),因此当float值绝对值小于这个数值时,转换后的half就是0.0。

当float类型绝对值大于0x477fffc0并小于0x7f800000时

当float类型绝对值最大为0x477fffc0时,转换的half值位65504(0x7bff),是half类型浮点数能表示的最大值,因此更大的float值转换为half后就是INF(但float绝对值大于0x7f800000时为NAN,转换成half也是NAN)。

当float类型的指数位数值大于0x70时

当float类型转换为half类型时,指数值需要减去0x70,并且由于相减后的结果仍然大于0,因此小数位只需要右移13bit即可。

当float类型的指数位数值小于或等于0x70时

由于half指数位最小只能表示2^-14,因此当float指数位小于或等于0x70(并且float的bit数值大于0x33800000)时,转换为half后指数位必为0,而右移13bit后的小数位需要先在第10bit位补1,然后再右移(0x70 - float指数位数值 + 1) bit。

代码

half f32_to_f16(float __x) {
  unsigned int x = *((unsigned int *)&__x);
  unsigned int sign = x & 0x80000000;
  unsigned int exponent_f32 = (x & 0x7f800000) >> 23;
  unsigned int mantissa_f32 = x & 0x007fffff;
  unsigned short y = (unsigned short)(sign >> 16);
  unsigned int exponent_f16;
  unsigned int mantissa_f16;
  unsigned int hx;

  hx = x & 0x7fffffff;

  if (hx < 0x33800000) { 
    return *((half *)&y);
  }
  if (hx > 0x7f800000) {
    y = 0x7e00;
    return *((half *)&y);
  }
  if (hx >= 0x477fffff) {
    y |= 0x7c00;
    return *((half *)&y);
  }

  mantissa_f16 = mantissa_f32 >> 13;

  if (exponent_f32 > 0x70) {
    exponent_f16 = exponent_f32 - 0x70;
  } else {
    exponent_f16 = 0;
    mantissa_f16 |= 0x400;
    mantissa_f16 = mantissa_f16 >> (0x71 - exponent_f32);
  }
  y = y | (unsigned short)(exponent_f16 << 10) | (unsigned short)mantissa_f16;
  return *((half *)&y);
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值