我有一个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
答案 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位或更好,因此使用long
(int
可能只是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++;
}
}