C 左换档和右换档,以防止分割损失

C 左换档和右换档,以防止分割损失,c,integer,division,pic,16-bit,C,Integer,Division,Pic,16 Bit,我不允许在我的C代码中使用浮点变量(出于性能原因)。我希望执行整数除法运算,同时我希望尽可能防止除法丢失 我的理解是,如果分子是一个大数,除法运算将产生良好的结果。目前,我正在对分子做一个左移运算,使其成为一个大数字,然后用分母除以分子。在最后的结果中,我做右移来补偿我原来的左移操作。我的问题是,这会改善分区结果吗 例如,为了实现x=y/z,我正在编写我的“C”代码,如下所示: x = y << 4; x = x / z; x = x >> 4; x=y>4; 你所说的

我不允许在我的C代码中使用浮点变量(出于性能原因)。我希望执行整数除法运算,同时我希望尽可能防止除法丢失

我的理解是,如果分子是一个大数,除法运算将产生良好的结果。目前,我正在对分子做一个左移运算,使其成为一个大数字,然后用分母除以分子。在最后的结果中,我做右移来补偿我原来的左移操作。我的问题是,这会改善分区结果吗

例如,为了实现
x=y/z
,我正在编写我的“C”代码,如下所示:

x = y << 4;
x = x / z;
x = x >> 4;
x=y>4;

你所说的除法损失到底是什么意思

如果您想要一个舍入除法,例如
div(19,10)->2
,并且您知道
x
y
是正数,您可以这样做:

(x + y / 2) / y
与除以
y
相比,除以
2
非常有效,除非
y
是编译时常数,在这种情况下,该除法将编译为乘法加上调整

您还必须避免除法溢出,例如按
0
除法或按
-1
除法
INT\u MIN

如果要计算比例,必须在除法之前执行乘法

out = out * ratio_n / ratio_d;
*
/
具有相同的优先级,并且是左关联的,这意味着
a*b/c
被解析为
(a*b)/c

您可能需要为中间结果使用较大的类型:

out = (long long)out * ratio_n / ratio_d;
您可以将这两种技术结合起来:

out = ((long long)out * ratio_n + ratio_d / 2) / ratio_d;
如果您的系统有16位
int
s,您应该只使用
long
作为中间类型,因为它保证至少有32位:

out = ((long)out * ratio_n + ratio_d / 2) / ratio_d;

但是请注意,如果结果超出了类型
int
的范围,则行为由实现定义。

您所说的除法损失到底是什么意思

如果您想要一个舍入除法,例如
div(19,10)->2
,并且您知道
x
y
是正数,您可以这样做:

(x + y / 2) / y
与除以
y
相比,除以
2
非常有效,除非
y
是编译时常数,在这种情况下,该除法将编译为乘法加上调整

您还必须避免除法溢出,例如按
0
除法或按
-1
除法
INT\u MIN

如果要计算比例,必须在除法之前执行乘法

out = out * ratio_n / ratio_d;
*
/
具有相同的优先级,并且是左关联的,这意味着
a*b/c
被解析为
(a*b)/c

您可能需要为中间结果使用较大的类型:

out = (long long)out * ratio_n / ratio_d;
您可以将这两种技术结合起来:

out = ((long long)out * ratio_n + ratio_d / 2) / ratio_d;
如果您的系统有16位
int
s,您应该只使用
long
作为中间类型,因为它保证至少有32位:

out = ((long)out * ratio_n + ratio_d / 2) / ratio_d;


但是请注意,如果结果超出了类型
int
的范围,则行为是由实现定义的。

否,它不会更改任何内容(某些性能损失除外)。放大所获得的一切,缩小所获得的一切都将丢失。您可以通过运行一些测试而不是询问来轻松地验证它。“除法损失”是由商是非整数值引起的,这显然不适合整数。完成后,您希望
x
具体包含什么内容?此技术唯一有帮助的情况是,当您希望提高某些中间计算的精度时,可以一直使用按比例增大的量,最后只进行按比例缩小。我只有一个简单的方程式out=out*(ratio\n/ratio\d)。我的代码是//Interpolate out=val[I]-val[I-1];out=(out*比率n)>2;out=out+val[i-1];如果你做一些取整,你的代码会更有意义。可能在将x向右移动之前添加0x08。但是,这一切都取决于上下文。也许最好的方法是使用不需要除法的算法。不,它不会改变任何东西(除了一些性能损失)。放大所获得的一切,缩小所获得的一切都将丢失。您可以通过运行一些测试而不是询问来轻松地验证它。“除法损失”是由商是非整数值引起的,这显然不适合整数。完成后,您希望
x
具体包含什么内容?此技术唯一有帮助的情况是,当您希望提高某些中间计算的精度时,可以一直使用按比例增大的量,最后只进行按比例缩小。我只有一个简单的方程式out=out*(ratio\n/ratio\d)。我的代码是//Interpolate out=val[I]-val[I-1];out=(out*比率n)>2;out=out+val[i-1];如果你做一些取整,你的代码会更有意义。可能在将x向右移动之前添加0x08。但是,这一切都取决于上下文。也许最好的方法是使用不需要除法的算法。当
x
y
为负数时,
(x+y/2)/y
需要工作。@chux:好的观点。负值对这个问题来说是个难题,我想不出一个优雅的方法来正确处理它们。@chux:奇怪的是,这可能是个例外。至少如果PIC标记碰巧引用了带有C18编译器的PIC18体系结构。我遇到的唯一一个C实现在舍入模式中利用了C89的灵活性,更糟糕的是,它也是我所知道的唯一一个不使用符号扩展右移的实现。@doynax:出于某种原因,我知道我不应该使用
y>>1
来避免潜在的未定义行为;-)我知道我认为的部门损失是关联的