2014-11-03 28 views
-2

我有一個Float值(32位)(範圍從-1.0到+1.0),需要將其轉換爲嵌入式應用程序C中的24位值(帶符號數據)。C中的浮點數爲24位整數

任何人都可以告訴我如何執行此轉換?

我想是這樣的:

浮點 - > 24位整數

-1.0 - > 0x00800000

-0.5 - > 0x00C00000

- 0.25 - > 0x00E00000

0.0 - > 0x00000000

0.25 - > 0x00200000

0.5 - > 0x00400000

1.0 - > 0x007FFFFF

+2

您可能想要提及您需要的確切24位格式。至少我不清楚24位值(簽名數據)。 – 2014-11-03 05:29:38

+0

如果你想表達範圍(-1.0; 1.0),你可以將其轉換爲(0.0,2.0),然後乘以(2^23-1)並將其轉換爲整數(你可以在前面舍入)。爲了轉換回你分開它然後減去1.0。請注意,它肯定會失去精確度。 – qwr 2014-11-03 06:00:15

+0

你爲什麼需要這個?但是你可以閱讀[this](http://stackoverflow.com/questions/7416699/how-to-define-24bit-data-type-in​​-c) – 2014-11-03 07:11:51

回答

-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++; 
    } 
} 
1

這是由0x7FFFFF浮子值乘以,將其轉換成一個整數的簡單並掩蓋掉更高位:

#include <math.h> 

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

請注意,這將映射-1.0到0x800001(-0x7FFFFF)。否則,映射將不是線性的。

我選擇了lround四捨五入到最接近的整數值的浮點值,四捨五入遠離零。當然,您可以選擇系統中可用的任何其他舍入方法,並具有所需的屬性。

0

我猜你想在這裏是浮動f轉換爲一個整數在某個單位等於2^23中的一個,因爲我們有23位數據的工作。例如。類似於音頻採樣器將如何進行。我假設你的浮點數在-1到1的範圍內,並且「自動」上限「任何」值。

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; 
    } 
} 
} 

注意:您將需要添加自定義代碼來處理你想要(南安-infinity和+ infiniy)方式的「特別」的浮點值。如果您在Windows環境中,則必須使用自己的無限代碼而不是使用標準宏。此代碼將需要<math.h>標題。

+0

我會說25位:0.0和1.0之間的'float'可以完全代表pow的所有乘積(1,-24 )作爲[binary32](http://en.wikipedia.org/wiki/Single-precision_floating-point_format)具有24位精度:23明確存儲,1暗示。然後是符號位。 – chux 2014-11-03 12:58:17

+0

你想要'int'函數'double a = abs(t);'或'double a = fabs(t);或浮動a = fabsf(t);'? – chux 2014-11-03 13:00:20

-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位int或更好,所以使用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你有它。 (在嵌入式世界中並不罕見)。