【问题标题】:float to fixed conversion with different scaling factors浮动到具有不同比例因子的固定转换
【发布时间】:2010-08-19 23:56:24
【问题描述】:

任何人都可以告诉我当我将固定转换为浮动并将浮动转换为固定时,这些方法之间有什么区别。

一) int a=32767; float b = 32765*(1/32767) // 16 bit scaling factor int c = b*32767;

b) int a=32767; float b = 32765*(1/1.0) // scaling factor=1 int c = b*1;

一) int a=32767; float b = 32765*(1/0x80000) // 24 bit scaling factor int c = b*(0x80000);

如果我的机器使用 Q23 定点表示,我应该使用哪个?

【问题讨论】:

  • 如果有人有什么想法,请告诉我。
  • 这是什么32765?在十六进制中它是0xfffd,所以这对我来说是完全出乎意料的。你为什么不改用0x10000

标签: floating-point fixed-point


【解决方案1】:

我没有找到关于你机器使用的“Q23定点表示”的详细信息,所以我自己定义,写了一些转换例程并测试了它们的一些值:

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

/**
 * q23 is a fixed-point two's-complement type:
 * - 1 bit sign,
 * - 8 bit integer part,
 * - 23 bit fraction part.
 *
 * long is assumed to be 32 bit two's complement without padding bits.
 */
typedef long q23;

static q23
cvt_float_to_q23(float f) {
  return f * (1 << 23);
}

static float
cvt_q23_to_float(q23 x) {
  return ((float) x) / (1 << 23);
}

/*
 * Here starts the testing code.
 */

static unsigned errors = 0;

static void
assert_q23_is(q23 fixed, float f) {
  if (cvt_q23_to_float(fixed) != f) {
    fprintf(stderr, "E: cvt_q23_to_float(%08lx) expected %.10f, got %.10f\n",
        fixed, f, cvt_q23_to_float(fixed));
    errors++;
  }
}

static void
assert_float_is(float f, q23 fixed) {
  if (cvt_float_to_q23(f) != fixed) {
    fprintf(stderr, "E: cvt_float_to_q23(%f) expected %08lx, got %08lx\n",
        f, fixed, cvt_float_to_q23(f));
    errors++;
  }
}

static void
assert_equals(q23 fixed, float f) {
  assert_q23_is(fixed, f);
  assert_float_is(f, fixed);
}

int
main() {
  /* Some values have equivalent representation. */
  assert_equals(LONG_MIN, -256.0f);
  assert_equals(LONG_MIN / 2, -128.0f);
  assert_equals(0, 0.0f);
  assert_equals(LONG_MAX / 2 + 1, 128.0f);

  /* There will be a fixpoint ... */
  assert_float_is(1.0 / 3, 0x002aaaaa);
  assert_q23_is(0x002aaaaa, 0.3333332539f);

  /* float only has 24 bits of precision */
  assert_equals(0x2aaaaac0, 256.0 / 3);

  if (errors == 0) {
    printf("ok\n");
    return EXIT_SUCCESS;
  }
  return EXIT_FAILURE;
}

一些备注:

  • 如果您需要饱和舍入,则必须通过检查 cvt_float_to_q23 的参数自行实现。
  • 到处都会有舍入误差,而且是不可避免的。请务必妥善处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-11
    • 1970-01-01
    • 2011-11-04
    相关资源
    最近更新 更多