Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我的定点算法实现正确吗?_C++_Fixed Point - Fatal编程技术网

C++ 我的定点算法实现正确吗?

C++ 我的定点算法实现正确吗?,c++,fixed-point,C++,Fixed Point,不久前,我创建了一组用于定点值操作的C宏。受到一些问题和答案的鼓舞,我希望在我的程序中计算密集的部分获得性能提升。虽然代码似乎产生了正确的结果,但我想知道它是否太幼稚/过于简单,因为它实际上比我的例程的常规浮点版本运行得慢(我在Wintel上进行双三次图像插值)。请看一下包含我的宏的这段简短代码,并提出一些改进建议,特别是在性能方面?谢谢 // these are architecture-dependent typedef short int fixed16; typedef int fixe

不久前,我创建了一组用于定点值操作的C宏。受到一些问题和答案的鼓舞,我希望在我的程序中计算密集的部分获得性能提升。虽然代码似乎产生了正确的结果,但我想知道它是否太幼稚/过于简单,因为它实际上比我的例程的常规浮点版本运行得慢(我在Wintel上进行双三次图像插值)。请看一下包含我的宏的这段简短代码,并提出一些改进建议,特别是在性能方面?谢谢

// these are architecture-dependent
typedef short int fixed16;
typedef int fixed32;
typedef __int64 fixed64;

// value of 2^n
#define POW2(n) (1 << n)

// create 16bit integer-based fixed point value from a floating point value, n is the number of bits reserved for the fractional part
#define FP_MAKE16(x, n) ((x) > 0.0 ? static_cast<fixed16>(floor((x) * POW2(n) + 0.5)) : static_cast<fixed16>(ceil((x) * POW2(n) - 0.5)))
// the same, 32bit
#define FP_MAKE32(x, n) ((x) > 0.0 ? static_cast<fixed32>(floor((x) * POW2(n) + 0.5)) : static_cast<fixed32>(ceil((x) * POW2(n) - 0.5)))
// and 64bit
#define FP_MAKE64(x, n) ((x) > 0.0 ? static_cast<fixed64>(floor((x) * POW2(n) + 0.5)) : static_cast<fixed64>(ceil((x) * POW2(n) - 0.5)))

// convert a fixed-point integer from one (n) format to another (m) assuming n < m
#define FP_CONVERT_UP(x, n, m) ((x) << (m-n))
// same for n > m
#define FP_CONVERT_DOWN(x, n, m) ((x) >> (n-m))

// convert floating-point value back to float
#define FP_FLOAT(x, n) (static_cast<float>(x) / POW2(n))
// same for double 
#define FP_DOUBLE(x, n) (static_cast<double>(x) / POW2(n))
// and for int. fractional part will be discarded! 
#define FP_INT(x, n) ((x) >> n)

// arithmetic operations for same-format numbers 
#define FP_NEG(a) ((~a)+1)
#define FP_ADD(a, b) ((a) + (b))
#define FP_SUB(a, b) ((a) + FP_NEG(b))
#define FP_MUL(a, b, n) (((a) * (b)) >> n)
#define FP_DIV(a, b, n) (((a) << n) / (b))
#define FP_POW2(a, n) (((a) * (a)) >> n)
#define FP_POW3(a, n) (((((a) * (a)) >> n)*(a)) >> n)

// arithmetic for different-format numbers, assuming n is the target (result) format and n > m
#define FP_ADD_UP(a, b, n, m) ((a) + ((b) << (n-m)))
#define FP_SUB_UP(a, b, n, m) ((a) + FP_NEG((b) << (n-m)))
#define FP_MUL_UP(a, b, n, m) (((a) * (b)) >> m)
#define FP_DIV_UP(a, b, n, m) (((a) << m) / (b))

// same for n < m
#define FP_ADD_DOWN(a, b, n, m) ((a) + ((b) >> (m-n)))
#define FP_SUB_DOWN(a, b, n, m) ((a) + FP_NEG((b) >> (m-n)))
#define FP_MUL_DOWN(a, b, n, m) (((a) * (b)) >> m)
#define FP_DIV_DOWN(a, b, n, m) (((a) << m) / (b))
//它们依赖于体系结构
typedef短整型16;
typedef int fixed32;
typedef__int64fixed64;
//2^n的值
#定义POW2(n)(1 0.0?静态施法(地板((x)*POW2(n)+0.5)):静态施法(天花板((x)*POW2(n)-0.5)))
//相同,32位
#定义FP_MAKE32(x,n)((x)>0.0?静态_铸造(地板((x)*POW2(n)+0.5)):静态_铸造(天花板((x)*POW2(n)-0.5)))
//和64位
#定义FP_MAKE64(x,n)((x)>0.0?静态_铸造(地板((x)*POW2(n)+0.5)):静态_铸造(天花板((x)*POW2(n)-0.5)))
//假设n>(n-m))
//将浮点值转换回浮点值
#定义浮点浮点(x,n)(静态浮点(x)/POW2(n))
//双人间也一样
#定义FP_-DOUBLE(x,n)(静态_-cast(x)/POW2(n))
//对于整数,分数部分将被丢弃!
#定义FP_INT(x,n)((x)>>n)
//相同格式数字的算术运算
#定义FP_NEG(a)((~a)+1)
#定义FP_加上(a,b)((a)+(b))
#定义FP_SUB(a,b)((a)+FP_NEG(b))
#定义FP_MUL(a,b,n)(((a)*(b))>>n)
#定义FP_DIV(a,b,n)((a)>n)
#定义FP_POW3(a,n)(a)*(a))>>n)*(a))>>n)
//不同格式编号的算术,假设n为目标(结果)格式,n>m
#定义FP_加法(a,b,n,m)((a)+(b)m)
#定义FP_DIV_UP(a,b,n,m)(((a)>(m-n)))
#定义FP_SUB_DOWN(a,b,n,m)((a)+FP_NEG((b)>>(m-n)))
#定义FP_MUL_DOWN(a,b,n,m)(((a)*(b))>>m)

#定义FP_DIV_DOWN(a,b,n,m)(((a)内联函数。使用它们。不要使用宏。使用类,重载它的运算符。而
static_cast
在C中不存在。这段代码非常糟糕,如果你发布一个使用它的代码示例,它将完全无法读取


请记住,浮点运算是在硬件中实现的,而您实现的定点运算是在软件中实现的。这种更改将受到惩罚,很可能是您的代码在算法级别的速度不够快,无法克服这种更改。

内联函数。使用它们。而不是宏。使用类,重载它的运算符。而C中不存在
static\u cast
。这段代码太可怕了,如果你用它发布一个代码示例,它将完全不可读


请记住,浮点运算是在硬件中实现的,而您实现的定点运算是在软件中实现的。这种更改将受到惩罚,很可能是您的代码在算法级别上不够快,无法克服这种更改。

您可以通过为imple编写一个重新配置。通过连续的配置可以实现简单的实现:

assert(FP_ADD(7, 5) == 12)
assert(FP_SUB(7, 5) == 2)
等等


覆盖足够的用例,直到您对代码有信心为止。此外,不要忘记在一个小ε内比较
double
s和
float
s。由于它们的位表示限制,相等可能无法按预期工作。

您可以通过为您的实现编写一个成功资产:

assert(FP_ADD(7, 5) == 12)
assert(FP_SUB(7, 5) == 2)
等等


覆盖足够的用例直到你对代码有信心。别忘了在小ε中比较<代码>双 s和<代码>浮点< /C> > s。由于位表示限制,等式可能无法正常工作。

< P>你可能应该从C++委员会读到这篇文章——“C++性能技术报告”。


<>这有效地扼杀了一些神话。

< P>你应该从C++委员会读到这篇文章——“C++性能技术报告”。


它有效地消除了一些误解。

这是对@neuviemeporte关于性能的评论的回应。我将此作为一个答案而不是评论,这样我可以更轻松地格式化代码

你说,“好吧,它们实际上是作为有调用开销的函数实现的”,还有“我猜结构成员也必须由某种指针引用;你不能逃避‘this’”。这两个问题表面上都是有效的,但让我们进一步研究

我在Linux上使用gcc/x86。考虑这个程序:

typedef int fixed32;
#define FP_ADD(a,b) ((a)+(b))
#define FP_NEG(a) ((~a)+1)
#define FP_SUB(a,b) ((a)+FP_NEG(b))
#define FP_INT(x,n) ((x)>>n)
#define FP_MUL(a,b,n) (((a)*(b))>>n)
#define FP_DIV(a,b,n) (((a)<<n)/(b))

template<class T, unsigned n>
struct Fixed {
private:
    T theBits;

public:
    Fixed(T t = T()) : theBits(t) {}

    Fixed operator+(const Fixed& rhs) const {
        return Fixed(theBits + rhs.theBits);
    }

    Fixed operator-(const Fixed& rhs) const {
        return Fixed(theBits - rhs.theBits);
    }

    Fixed operator~() const {
        return Fixed(~theBits);
    }

    Fixed operator*(const Fixed& rhs) const {
        return Fixed((theBits*rhs.theBits)>>n);
    }

    Fixed operator/(const Fixed& rhs) const {
        return Fixed((theBits<<n)/rhs.theBits);
    }

    operator T() const {
        return theBits >> n;
    }
};

int DoFpAdd(const fixed32 a, const fixed32 b) {
     fixed32 result = FP_ADD(a, b);
     return FP_INT(result, 16);
}

int DoFixedAdd(const Fixed<int, 16> a, const Fixed<int, 16> b) {
    return a+b;
}


int DoFpSub(const fixed32 a, const fixed32 b) {
     fixed32 result = FP_SUB(a, b);
     return FP_INT(result, 16);
}

int DoFixedSub(const Fixed<int, 16> a, const Fixed<int, 16> b) {
    return a-b;
}

int DoFpMul(const fixed32 a, const fixed32 b) {
     fixed32 result = FP_MUL(a, b, 16);
     return FP_INT(result, 16);
}

int DoFixedMul(const Fixed<int, 16> a, const Fixed<int, 16> b) {
    return a*b;
}

int DoFpDiv(const fixed32 a, const fixed32 b) {
     fixed32 result = FP_DIV(a, b, 16);
     return FP_INT(result, 16);
}
int DoFixedDiv(const Fixed<int, 16> a, const Fixed<int, 16> b) {
    return a/b;
}
typedef int fixed32;
#定义FP_加上(a,b)((a)+(b))
#定义FP_NEG(a)((~a)+1)
#定义FP_SUB(a,b)((a)+FP_NEG(b))
#定义FP_INT(x,n)((x)>>n)
#定义FP_MUL(a,b,n)(((a)*(b))>>n)
#定义FP_DIV(a,b,n)((a)n);
}
固定运算符/(常数固定和rhs)常数{
返回固定的((位n;
}
};
int DoFpAdd(常数固定32 a,常数固定32 b){
fixed32结果=FP_添加(a,b);
返回FP_INT(结果,16);
}
int dofixedd(常数固定a,常数固定b){
返回a+b;
}
int DoFpSub(常数固定32 a,常数固定32 b){
fixed32结果=FP_SUB(a,b);
返回FP_INT(结果,16);
}
int DoFixedSub(常数固定a,常数固定b){
返回a-b;
}
int DoFpMul(常数固定32 a,常数固定32 b){
fixed32结果=FP_MUL(a,b,16);
返回FP_INT(结果,16);
}
int DoFixedMul(常数固定a,常数固定b){
返回a*b;
}
int DoFpDiv(常数固定32 a,常数固定32 b){
fixed32结果=FP_DIV(a,b,16);
返回FP_INT(结果,16);
}
int DoFixedDiv(常数固定a,常数固定b){
返回a/b;
}
我用计算机编译了它