浮点到C中的24位整数

时间:2014-11-03 05:24:57

标签: c bit-manipulation signal-processing

我有一个Float值(32位)(范围-1.0到+1.0),这需要在C中转换为24位值(带符号数据),用于嵌入式应用程序。

有人可以告诉我如何执行此转换?

我想要这样的东西:

浮动 - > 24位整数

-1.0 - > 0x00800000

-0.5 - > 0x00C00000

-0.25 - > 0x00E00000

0.0 - > 00000000

+0.25 - > 0x00200000

+0.5 - > 0x00400000

+1.0 - > 0x007FFFFF

4 个答案:

答案 0 :(得分:1)

这就像将浮点值乘以0x7FFFFF,将其转换为整数类型,并屏蔽较高位一样简单:

#include <math.h>

int convert(double val) {
    return lround(val * 0x7FFFFF) & 0xFFFFFF;
}

请注意,这会将-1.0映射到0x800001(-0x7FFFFF)。否则映射将不是线性的。

我选择lround来舍入浮点值,该值舍入到最接近的整数值,从零开始舍入中间情况。当然,您可以选择系统上可用的任何其他舍入方法,并具有所需的属性。

答案 1 :(得分:0)

我猜你想要的是浮动f转换为某个单位的整数,等于2 ^ 23中的一个,因为我们有23位数据可供使用。例如。类似于音频采样器如何做到这一点。我假设您的浮点数在-1到1的范围内,并且'ceiling'自动超出其范围内的任何值。

uint32_t convert(float f) {
// Special code for NaN and infinity...
if(isnan(f) || !isfinite(f)) {
    return 0;
}

// Make sure f is in the conversion range
// Use a 'double' here to support all normal float values for f.
double t = f * 8388608.0f;
double a = abs(t);
if(a > 8388608.0f) {
    if(f > 0) {
        // f is a 'large' number (>=1.0) 
        // return the largest integer.
        return 0x007FFFFF;
    } else {
        // f is a 'large negative' number (<= -1.0)
        // return the largest negative integer
        return 0x00800000;
    }
} else {
    // Manual two's complement integer creation
    if(f >= 0) {
        return (uint32_t) a;
    } else {
        return 0x01000000 - (uint32_t) a;
    }
}
}

注意:您需要添加自定义代码以按照您想要的方式处理“特殊”浮点值(NaN,-infinity和+ infiniy)。如果您使用的是Windows环境,则必须使用自己的isfinite代码而不是使用标准宏。此代码需要<math.h>标头。

答案 2 :(得分:-1)

OP的请求可能有点误解。

-1.0  --> 0x00800000
-0.5  --> 0x00C00000
-0.25 --> 0x00E00000
 0.0  --> 0x00000000
+0.25 --> 0x00200000
+0.5  --> 0x00400000
+1.0  --> 0x007FFFFF ???

最后一个数据点更可能是

(+1.0 - pow(2,-23)) --> 0x007FFFFF

假设输入为float,输出需要24位或更好,因此使用longint可能只是16位)

#include <math.h>

long convert(float value) {
    return (long) roundf(value * 0x800000);
}

或者非便携地,可以添加3.0以将输入放在[2.0到4.0]范围内并将这些位从联合中拉出来。

uint32_ t convert2(float value) {
  union {
    uint32_t i;
    float f;
  } x;
  x.f = value + 3.0f;
  return (x.i - 0x00800000) & 0x00FFFFFF; 
}

返回类型可能是int24_t你有它。 (在嵌入式世界中并非罕见。)

答案 3 :(得分:-1)

感谢大家的回复。

不幸的是我不能在我的开发环境中使用“math.h”。

我在微控制器论坛中找到了一种优化的方法。

typedef union{
    struct{
        Uint16 lo;
        Uint16 hi;
    }u16;
    Uint32 u32;
    int32 i32;
    float  f;
}Versatype32;

void Float_to_I24bit(int *dest, float *src, Uint32 length)
{
register Versatype32 data;

    while(length--){
        data.f = *src;
        data.i32 = ((int32)(data.f * 8388608) & 0x00ffffff);
        *dest++ = data.u16.hi;
        *dest++ = data.u16.lo;
        src++;
    }
}