c++ - 为什么在将中间结果分配给 int 之前将其转换为 long?
问题描述
在 Codeforces 和 Codechef 的许多编码流和解决方案中,我看到当数字有点大并且我们需要将其分配给 int 时,我们将其转换为 long 而不是将其转换为 int
int maxAreaOfCake(int h, int w, vector<int>& hCuts, vector<int>& vCuts)
{
hCuts.push_back(0);
hCuts.push_back(h);
vCuts.push_back(0);
vCuts.push_back(w);
int MOD = 100000007;
sort(hCuts.begin(), hCuts.end());
sort(vCuts.begin(), vCuts.end());
int horizontal = 0;
for(int i = 0; i < (int)hCuts.size() - 1; i++) horizontal = max(horizontal, hCuts[i+1] - hCuts[i]);
int vertical = 0;
for(int i = 0; i < (int)vCuts.size() - 1; i++) vertical = max(vertical, vCuts[i+1] - vCuts[i]);
return (int) ((long)horizontal%MOD * (long)vertical%MOD)%MOD;
}
这是leetcode中MaxAreaOfCake问题的解决方案。在这里,由于返回类型是 int,我们最终将转换为 int,但在此之前,我们首先将其转换为 long。当我尝试将 long 更改为 int 时,出现运行时错误。如果有人知道答案,请分享:)
解决方案
有问题的行是
return (int) ((long)horizontal%MOD * (long)vertical%MOD)%MOD;
强制转换为 long 确保表达式(long)horizontal%MOD * (long)vertical%MOD
是两个long
值的乘积。C 和 C++ 将算术运算的结果计算为其操作数的“最大”类型;如果你将两个int
s 相乘,结果也是int
如此。如果数学结果对于 int 而言太大,则会导致有符号溢出,这是未定义的行为。horizontal%MOD * vertical%MOD
如果大于maximum ,就会发生这种情况int
,例如因为操作数大于最大值的平方根int
。为了防止代码将操作数转换为long
,希望long
' 的值范围更大(这可能是也可能不是真的)。如果它是真的,结果通常总是适合一个long
(因为通常最大int
小于最大long
) 的平方根。然后使用乘法的结果来计算它的模MOD
,它永远不会大于MOD-1
并且因此小于最大值int
。因此,将最终结果转换回 是安全的int
,这是第一个(int)
所做的。但是大的中间结果,在最终模之前,必须在更大的值范围类型中计算。
考虑一下为了使这个逻辑健壮而必须执行的情况(如果 long
并且int
具有相同的值范围,则强制转换是徒劳的)我希望有一个std::numeric_limits<T>
类似的模板bool would_overflow(T2 arg)
,用于 T2 类型的每个 arg 返回该值是否可转换到 T 而不会溢出。
推荐阅读
- r - 在 r 中返回指标排名
- node.js - 获取 max updatedAt 的 X 值,聚合组
- javascript - 在自定义电子文本编辑器中保存换行符
- node.js - 从 MongoDb 集合中检索前 5 个字段
- firebase - Flutter 应用程序中的辅助 Firebase 项目
- c# - XMLDocument VS XmlReader 更有效地在 C# 中验证格式良好的 XML
- excel - 大家好,我刚开始使用 Excel VBA,有一个启动问题
- r - 匹配具有乘法误差的线性模型的 lm 和 optim 系数估计
- parallel-processing - 在 Java 中“即时”生成并行执行任务
- sitecore - sitecore 媒体库是 DAM 吗?