C 左换档和右换档,以防止分割损失
我不允许在我的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; 你所说的
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
来避免潜在的未定义行为;-)我知道我认为的部门损失是关联的