CPP:防止溢出的类型转换
CPP: Type casting to prevent overflows
我写的值可能溢出的语句如下:
fact = ((fact * (llu) (i - 1)) / (llu) (i - M)) % MOD;
llu Ans = (llu) C[k - 1] * fact;
这里llu
表示unsigned long long
i
是一个有符号整数,取值范围从210到220
MOD
= 109 + 9
变量fact
和Ans
的类型为unsigned long long
。
M
是一个有符号整数,最多可以是210
C[k - 1]
是int
数组C
的(k - 1)
索引项,其数量级为109
所有值总是正。
问题:现在,关于我在上面的代码中所做的类型转换(从int
到unsigned long long
);它是否足以处理溢出,或者我是否做了更多/更少/不正确的类型转换?
此外,在我的代码的第一行执行(i - M)
除法是正确的,还是应该最好写成:
fact = fact * (llu) (i - 1);
fact = (fact / (llu) (i - M)) % MOD;
您没有定义fact的限制,因为它是第一个表达式的一部分。例如,如果fact最初可以是2^60,那么就会出现溢出。
当你乘整数位值时,你需要把位数加起来。例如,如果你将两个32位的值相乘,你将需要/得到32+32 = 64位。
fact=((fact*(llu)(i-1))/(llu)(i-M))%MOD;
在我们的示例中,i最多为20位,这意味着为了避免第一个表达式中的溢出事实必须最多为Bitsof(unsigned long long)-20。如果unsigned long long是64位,那么事实上可以高达44位,例如2^44。
llu Ans=(llu)C[k-1]*fact;
在第二个表达式中,我们有类似的情况,事实必须最多64-30位(10^9大约需要29位),在计算第一个表达式后,这是由%MOD表达式验证的。Fact将小于第一个表达式后的10^10,这几乎是32位。
简短的回答:如果fact初始值小于2^44,则它不会溢出。
在这种情况下,我更喜欢使用显式的整数大小,例如类型u_int64_t,我知道它是无符号64位。相关文章:
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++中的双指针类型转换
- 逐位操作的隐式类型转换
- 模板中的类型转换
- 在 C++(和 C)中进行类型转换时明显不一致
- 获取隐式转换溢出从无符号到已签名的警告
- 字符类型转换不兼容
- 将复杂的非基元C++数据类型转换为 Erlang/Elixir 格式,以使用 NIF 导出方法
- C++:用户定义的显式类型转换函数错误
- 将类指针类型转换为键时出错
- 通过引用传递参数时C++类型转换
- 在 C++ 中将一个模板类型的对象类型转换为另一个模板类型
- C++显式类型转换(C 样式强制转换)的强制表示法和static_cast的多种解释
- C++无效的函数类型转换
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 如何将Windows产品类型转换为名称?
- 通过构造函数方法输出的类到类类型转换是 5500 为什么不是 5555
- 长类型Max等于int Max error + math.h pow()编译警告:隐式常量转换溢出
- CPP:防止溢出的类型转换