C ++:键入强制转换以防止溢出

时间:2014-03-12 19:33:44

标签: c++ optimization

我正在写的值可能会溢出的声明如下:

fact = ((fact * (llu) (i - 1)) / (llu) (i - M)) % MOD;
llu Ans = (llu) C[k - 1] * fact;

此处llu表示unsigned long long

i是有符号整数,在2 10 到2 20 的值之间变化

MOD是10 9 + 9

变量factAns属于unsigned long long类型。

M是有符号整数,最高可达2 10

C[k - 1](k - 1)数组int的{​​{1}}索引术语,大约为10 9

所有值始终为正。

问题: 现在,关于我在上面的代码中完成的类型转换(从Cint);它是否足以处理溢出或我做更多/更少/不正确的类型转换?

此外,在我的代码的第一行中按unsigned long long进行除法是否正确,或者最好将其写为:

(i - M)

1 个答案:

答案 0 :(得分:1)

你没有定义 fact 的限制,因为它是第一个表达式的一部分。如果 fact 最初可以是2 ^ 60,那么你就有溢出。

当您乘以整数位值时,需要对位数求和。例如,如果您需要多个两个32位值,则需要/得到32 + 32 = 64位。

fact=((fact*(llu)(i-1))/(llu)(i-M))%MOD;

在我们的示例中,我们 i 最多20位,这意味着为了避免第一个表达式中的溢出事实必须至多为Bitsof(unsigned long long) -20。如果无符号长long为64位,则事实最多可为44位,例如2 ^ 44。

llu Ans=(llu)C[k-1]*fact;

在第二个表达式中我们有类似的情况,事实在评估第一个表达式之后必须至多为64-30位(10 ^ 9需要大约29位),这是由%MOD表达式。在第一次表达之后,事实将小于10 ^ 10,几乎是32位。

简短回答:如果事实最初小于2 ^ 44则不会溢出。

在这种情况下,我更喜欢使用显式整数,例如类型 u_int64_t ,我知道它是无符号的64位。