2008-10-09 60 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。