在不使用float,double或division的情况下舍入整数

San*_*996 6 c math rounding

它的嵌入式平台就是为什么会出现这种限制.

original equation: 0.02035*c*c - 2.4038*c
Run Code Online (Sandbox Code Playgroud)

做过这个:

int32_t val = 112; // this value is arbitrary
int32_t result = (val*((val * 0x535A8) - 0x2675F70));
result = result>>24;
Run Code Online (Sandbox Code Playgroud)

精度仍然很差.当我们相乘时,val*0x535A8我们可以通过舍入来进一步提高精度,但不使用任何浮点数,双精度或除法.

Mar*_*som 2

问题不在于精度。您使用了大量的位。

我怀疑问题在于您正在比较两种不同的转换为int. 第一个是 a 的强制转换double,第二个是右移截断。

将浮点转换为整数只是删除小数部分,导致向零舍入;右移进行向下舍入或向下舍入。对于正数没有区别,但对于负数这两种方法将彼此相差 1。请参阅http://ideone.com/rkckuy上的示例以及Wikipedia上的一些背景阅读。

您的原始代码很容易修复:

int32_t result = (val*((val * 0x535A8) - 0x2675F70));
if (result < 0)
    result += 0xffffff;
result = result>>24;
Run Code Online (Sandbox Code Playgroud)

请访问http://ideone.com/D0pNPF查看结果

您也可能只是认为正确的移位结果就可以了。转换误差并不比其他方法大,只是不同。

编辑:如果您想进行舍入而不是截断,答案会更简单。

int32_t result = (val*((val * 0x535A8) - 0x2675F70));
result = (result + (1L << 23)) >> 24;
Run Code Online (Sandbox Code Playgroud)

我将与其他一些人一起建议您使用常量表达式将这些魔术常量替换为记录它们如何派生的内容。

static const int32_t a = (int32_t)(0.02035 * (1L << 24) + 0.5);
static const int32_t b = (int32_t)(2.4038 * (1L << 24) + 0.5);
int32_t result = (val*((val * a) - b));
Run Code Online (Sandbox Code Playgroud)