如何使用(a * X)/ b公式中的两个可能更大的数字来重新缩放int

时间:2012-04-23 11:34:54

标签: c integer-arithmetic

我在c中有一个如下所示的公式:

X = (a * X) / b;

这用于使用X重新定标a/b。但是X是16位无符号整数,与a的乘法很容易溢出。我怎样才能使用具有准确结果的整数进行计算。

我当然可以使用浮点运算,但是这个操作很有可能在没有浮点硬件的处理器上运行。

编辑:我忘了说a和b都是32位无符号整数。 好吧,我的回答是右移ab,直到它们都符合16位。那样a * X最多为32位,最终计算是准确的。

2 个答案:

答案 0 :(得分:3)

您可以这样重写:

X = (a/b)*X + (a%b)*(X/b) + (a%b)*(X%b)/b

如果你可以确定其中任何一个都没有溢出(第一个是近似结果,第二个小于结果,第三个股息大约b^2)。

为什么有效(假设没有溢出,/表示普通除法,div整数除法):

X div Y =def floor(X/Y)
X =def (X div Y) * Y + X mod Y

(X*Y) div Z = floor(X*[(Y div Z) * Z + Y mod Z] / Z)
  = floor(X*(Y div Z)*Z/Z + X*(Y mod Z)/Z)
  = X*(Y div Z) + X*(Y mod Z) div Z

现在,如果我们使用它两次(具有运算符的C含义):

X = (a*X)/b = X*(a/b) + X*(a%b)/b =
            = X*(a/b) + (a%b)*(X/b) + (a%b)*(X%b)/b

但如果可能的话,我会建议以更高的精度进行计算

X = ((int)X*a)/b

答案 1 :(得分:3)

您可以将a提升为更大的数据类型,例如:

X = ((long)a * X) / b;