C++ 对于非常大的非负n和m,n%=m是否可以返回负值?
这个问题是关于模运算符C++ 对于非常大的非负n和m,n%=m是否可以返回负值?,c++,operators,largenumber,C++,Operators,Largenumber,这个问题是关于模运算符%。我们知道,通常a%b在a除以b且余数大于或等于零且严格小于b时返回余数。但当a和b的震级为10^9时,上述情况是否成立 对于以下输入代码,我似乎得到了负输出: 74 41 28 但是,更改最终输出语句会起作用,并且结果会变得正确 #include<iostream> using namespace std; #define m 1000000007 int main(){ int n,k,d;
%
。我们知道,通常a%b
在a除以b且余数大于或等于零且严格小于b时返回余数。但当a和b的震级为10^9时,上述情况是否成立
对于以下输入代码,我似乎得到了负输出:
74 41 28
但是,更改最终输出语句会起作用,并且结果会变得正确
#include<iostream>
using namespace std;
#define m 1000000007
int main(){
int n,k,d;
cin>>n>>k>>d;
if(d>n)
cout<<0<<endl;
else
{
long long *dp1 = new long long[n+1], *dp2 = new long long[n+1];
//build dp1:
dp1[0] = 1;
dp1[1] = 1;
for(int r=2;r<=n;r++)
{
dp1[r] = (2 * dp1[r-1]) % m;
if(r>=k+1) dp1[r] -= dp1[r-k-1];
dp1[r] %= m;
}
//build dp2:
for(int r=0;r<d;r++) dp2[r] = 0;
dp2[d] = 1;
for(int r = d+1;r<=n;r++)
{
dp2[r] = ((2*dp2[r-1]) - dp2[r-d] + dp1[r-d]) % m;
if(r>=k+1) dp2[r] -= dp1[r-k-1];
dp2[r] %= m;
}
cout<<dp2[n]<<endl;
}
}
#包括
使用名称空间std;
#定义m 100000007
int main(){
int n,k,d;
cin>>n>>k>>d;
如果(d>n)
cout这是由int
范围施加的限制
int
只能保存介于-2147483648到2147483647之间的值
考虑对m、n、k、d&r变量使用long-long
。如果您的计算不应该有负值,请尽可能使用unsigned long-long
long-long
可以保存从-9223372036854775808到9223372036854775807的值
而无符号long-long
可以保存0到18446744073709551615之间的值(2^64)
与无符号类型相比,有符号类型的正值范围大约减少了一半,这是因为最高有效位用于符号;当您尝试分配大于指定数据类型所施加范围的正值时,最高有效位将升高,并被解释为负值从数学上讲,大数字并没有什么特别之处,但计算机只有有限的宽度来记录数字,所以当事情变得太大时,就会出现“溢出”错误。一个常见的类比是汽车仪表板上行驶英里数的计数器-最终它将显示为所有9并转为0。由于负数的处理方式,标准有符号整数不会转为零,而是转为非常大的负数
您需要切换到更大的变量类型,以便它们溢出的速度更快——“long int”或“long long int”而不仅仅是“int”,范围每增加一个宽度位就加倍。由于没有范围用于负数,因此也可以使用无符号类型进行进一步加倍。嗯,不,正操作数的模运算不会产生负结果
然而
int类型仅由C标准保证支持范围为-32767到32767的值,这意味着您的宏m不一定要扩展为int类型的文本。它将适合较长的范围(保证有足够大的范围)
如果发生这种情况(例如,具有16位int类型和32位long类型的编译器),则模运算的结果将被计算为long,并且可能具有超过int所能表示的值。将该值转换为int(由于dp1是指向int的指针,dp1[r]]=m等语句将需要此值)提供未定义的行为。可以容纳int
或long
的值是实现定义的,并且变化很大。如果您尝试分配超出范围的值,结果是实现定义的;您不一定会得到负值……但是,好的编译器会发出警告。遗憾的是,许多新程序员用于忽略它们,因为“它们不是错误,对吗?”IIRC:不适合的转换结果是实现定义的,而不是未定义的行为。(不适合的操作的结果是未定义的行为,但这不能发生在%
中)
if(dp2[n]<0) cout<<dp2[n]+m<<endl;
else cout<<dp2[n]<<endl;