2008-10-09 62 views
20

在C++中,將任何浮點值(float)轉換爲fixed point(int,16:16或24:8)的通用方法是什麼?將浮點轉換爲定點

編輯:爲了澄清,定點值有兩個部分:整數部分和小數部分。整數部分可以用有符號或無符號整數數據類型表示。小數部分由無符號數據整數數據類型表示。

爲了清楚起見,我們用錢比喻一下。小數部分可能代表美分 - 美元的一小部分。 「美分」數據類型的範圍應該是0到99.如果一個8位無符號整數用於定點數學,那麼小數部分將被分成256個均勻可分的部分。

我希望能夠解決問題。

+0

如果您使用Visual C++,在考慮將所有浮點重構爲固定點之前,先試驗`/ fp:fast`開關。這個浮點模型開關允許優化,這可以允許浮點輕鬆地跳動固定點的速度。絕對是一個低估的功能。 – 2015-12-30 17:24:01

回答

26

在這裏你去:

// A signed fixed-point 16:16 class 
class FixedPoint_16_16 
{ 
    short   intPart; 
    unsigned short fracPart; 

public: 
    FixedPoint_16_16(double d) 
    { 
     *this = d; // calls operator= 
    } 

    FixedPoint_16_16& operator=(double d) 
    { 
     intPart = static_cast<short>(d); 
     fracPart = static_cast<unsigned short> 
        (numeric_limits<unsigned short> + 1.0)*d); 
     return *this; 
    } 

    // Other operators can be defined here 
}; 

編輯:下面是基於anothercommon的方式來處理定點數(和KPexEA指出)一個更一般的類:

template <class BaseType, size_t FracDigits> 
class fixed_point 
{ 
    const static BaseType factor = 1 << FracDigits; 

    BaseType data; 

public: 
    fixed_point(double d) 
    { 
     *this = d; // calls operator= 
    } 

    fixed_point& operator=(double d) 
    { 
     data = static_cast<BaseType>(d*factor); 
     return *this; 
    } 

    BaseType raw_data() const 
    { 
     return data; 
    } 

    // Other operators can be defined here 
}; 


fixed_point<int, 8> fp1;   // Will be signed 24:8 (if int is 32-bits) 
fixed_point<unsigned int, 16> fp1; // Will be unsigned 16:16 (if int is 32-bits) 
+3

這更多關於如何剖析浮點數而不是將其轉換爲固定點表示。 – Trap 2009-03-31 00:50:06

+1

numeric_limits ** :: ???? ** 我認爲有一部分缺失。 – Ant 2011-02-02 12:18:55

0

這對於將浮點數轉換爲整數很合適,但OP也希望得到fixed point。我不知道(C++不是我可以輕易想到的東西)。在C++中,如何做到這一點,我不知道(C++並不是我能想到的東西)。也許可以嘗試縮放整數方法,即使用32位或64位整數,並以編程方式將最後的6位數字分配給小數點右側的內容。

18

從浮點數轉換爲整數會丟棄小數部分,所以如果你想保留這個小數部分作爲固定點,那麼你只需在浮點數之前乘以浮點數就可以了。下面的代碼不會檢查你的溢出。

如果你想要16:16

double f = 1.2345; 
int n; 

n=(int)(f*65536); 

如果你想24:8

double f = 1.2345; 
int n; 

n=(int)(f*256); 
-4

沒有任何內置在支持C++的點數。你最好的選擇是編寫一個包裝器'FixedInt',它需要雙打併轉換它們。

至於通用的方法轉換... int部分很容易,只需抓住值的整數部分,並將其存儲在高位...小數部分將沿着以下幾行:

for (int i = 1; i <= precision; i++) 
{ 
    if (decimal_part > 1.f/(float)(i + 1) 
    { 
     decimal_part -= 1.f/(float)(i + 1); 
     fixint_value |= (1 << precision - i); 
    } 
} 

雖然這很可能包含bug仍然

6

****編輯**:我的第一個意見適用於凱文的編輯之前,但我會離開這裏爲後人。答案有時會在這裏很快改變!

凱文的方法的問題是,與固定點你通常打包成一個保證字大小(通常32位)。分別聲明這兩個部分會讓您感受到編譯器結構打包的奇思妙想。是的,你可以強制它,但它不適用於16:16表示以外的任何其他功能。

KPexEA通過將所有內容打包成int來更接近標記 - 儘管我會使用「signed long」來試圖在32位上進行顯式指定。然後,您可以使用他的方法來生成定點值,並且位切片會再次提取組件部分。他的建議還包括24:8的情況。

(和其他人誰建議剛的static_cast .....你在想什麼;?))

1

我給這個問題的答案寫的最好的答案的傢伙,但我真的使用的相關問題代碼那點here

它使用了模板,並且很容易依賴於boost lib。