我对c ++和i代码的经验较少,主要是在python中。在网上解决一些编程挑战时,有一部分代码我需要将两个数字相乘并用mod减少它。
v = (u*node) % 100000
其中u和node是int值,范围为1 - 100000.由于时间限制问题,我用c ++编写了我的代码。这就是我写的
long long v = (u * node) % 100000;
提交时我在所有测试用例中都遇到了运行时错误。我下载了失败的测试用例并在我的本地计算机上运行,我得到了完美的输出。
看完社论之后,我将这一行改为
long long v = u;
v = (v*node) % 100000;
并提交。我通过了所有测试用例。请任何人解释这两行之间的区别..
可变数据类型 -
int u
int node
答案 0 :(得分:4)
因为u
和node
都是int
s,所以这个表达式
(u * node)
产生int
结果。如果它溢出 - 意味着结果太大而不适合int
- 太糟糕了。有符号整数溢出为undefined behavior,所有投注均已关闭。有可能,它会像环绕一样,但它也可以格式化你的硬盘。
当您u
成为long long int
时,相同的表达式会产生long long int
结果。 node
被乘数被隐式提升到long long int
(int
到long long int
是一个扩展转换,所以它总是安全的),然后这两个long long int
值会成倍增加。此操作不会溢出,因此您可以避免未定义的行为并获得正确的结果。
您也可以使用显式强制转换编写代码以避免声明新变量:
(static_cast<long long int>(u) * node)
请注意,您提升的值并不重要,结果将是相同的,因为其他值将被隐式提升,如上所述:
(u * static_cast<long long int>(node))
另一方面,这不起作用:
static_cast<long long int>(u * node)
因为它只加宽了乘法运算的结果,在执行了乘法之后。如果该乘法溢出int
类型,则已经太晚了。
这也是不起作用的原因 - 在结果被评估为long long
后,int
促销发生:
long long v = (u * node)
答案 1 :(得分:2)
请有人解释这两行之间的区别。
第一行实际上是指:
long long v = (long long) (int * int % int);
所以,首先你将int乘以int, get overflow ,截断为int ,mod,将int扩展为long long
下一行实际意思是:
long long v = (long long) int;
v = long long * int % int;
所以,首先将int扩展为long ,多个long by int, no overflow ,mod,赋值给long long
答案 2 :(得分:0)
可能你在第一种情况下遇到了溢出(u和v都是整数)。这是因为当乘法变量时,编译器会将结果保存在一个临时变量中,该变量与乘法中变量的最高类型(int,float,double等)的类型相同。所以,如果你乘以两个大整数,结果就会溢出。
您的修改有效,因为临时结果存储在很长的时间内,在示例中不会溢出。