user-0 提问: 怎么解决3n+1，溢出问题？

回复:
user: user-1
content: n =3*n+1;     n/=2 ; 改成             n = n+ (n+1)/2;  原来 3倍+1，现在降到 1.5 左右，正符合适度缓解的情况。 64位，则可以提高表示范围，更大精度缓解了溢出问题。  你要确保没问题，高精度计算估计跑不了。

user: user-1
content: 否则你就高精度吧。

user: user-1
content: 引用 3 楼 lm_whales 的回复:n =3*n+1;     n/=2 ; 改成             n = n+ (n+1)/2;   [quote=引用 楼主 zhang5476499 的回复:] 3n+1问题是一个简单有趣而又没有解决的数学问题。这个问题是由L. Collatz在1937年提出的。克拉兹问题（Collatz problem）也被叫做hailstone问题、3n+1问题、Hasse算法问题、Kakutani算法问题、Thwaites猜想或者Ulam问题。 问题如下： （1）输入一个正整数n； （2）如果n=1则结束； （3）如果n是奇数，则n变为3n+1，否则n变为n/2； （4）转入第（2）步。    #include<stdio.h> #include<math.h> int main() { 	int n; 	int count=0; 	scanf("%d",&n); 	while(1<n) 	{ 		if(n%2==1) 		{ 			n=3*n+1; 			n/=2; 		} 		else 		{ 			n=n/2; 		} 		count++; 		if(n==1) break; 	} 	printf("%d\n",count);  	return 0; } 刘汝佳的书上就写着：因为n为奇数时候3n+1一定是偶数，下一步将其立刻除以2.如果将将两次操作一起做，可以在一定程度上缓解这个问题。我就是这么做的，但是输出987654321时候还是溢出拉。[/quote]  接着改成zhao4那种形式

user: user-2
content: #include<stdio.h> #include<math.h> #include <conio.h> int main() { 	unsigned int n; 	int count=0; 	scanf("%d",&n);  	while(n>1) 	{ 		if(n & 1) 		{ 			//n=3*n+1; 			n=n+(n+1)/2; 			//n/=2; 			count++; 		} 		else 		{ 			n=n/2; 		} 		count++; 	} 	printf("%d\n",count); 	getch(); 	return 0; }  LZ验证一下吧

user: user-3
content: #用python吧，不用担心溢出 def n3n1(n):     count=0     while n>1:         if n%2==1:             n=3*n+1             n=n/2         else:             n=n/2         count+=1         if n==1:             break     return count  print n3n1(1000000000000000000000000000000000000000000)  #输出517

user: user-2
content: (3n+1)/2==> n+(n+1)/2

user: user-4
content: 32位的int，去掉符号位，最大不是2147483648吗？  你的987654321*3+1肯定大于这个值，能不溢出吗？  所以老赵使用64位的int是正解。但如果你要无限运算下去，则需要自己写一个大数计算函数，自己通过数组来完成四则运算。

user: user-5
content: #include <iostream> #include <string> using namespace std; inline int compare(string str1,string str2) {//相等返回0，大于返回1，小于返回-1          if (str1.size()>str2.size()) return 1; //长度长的整数大于长度小的整数     else if (str1.size()<str2.size()) return -1;     else                              return str1.compare(str2); //若长度相等，则头到尾按位比较 } string SUB_INT(string str1,string str2); string ADD_INT(string str1,string str2) {//高精度加法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         if (str2[0]=='-') {             sign=-1;             str=ADD_INT(str1.erase(0,1),str2.erase(0,1));         } else {             str=SUB_INT(str2,str1.erase(0,1));         }     } else {         if (str2[0]=='-') {             str=SUB_INT(str1,str2.erase(0,1));         } else { //把两个整数对齐，短整数前面加0补齐             string::size_type L1,L2;             int i;             L1=str1.size();             L2=str2.size();             if (L1<L2) {                 for (i=1;i<=L2-L1;i++) str1="0"+str1;             } else {                 for (i=1;i<=L1-L2;i++) str2="0"+str2;             }             int int1=0,int2=0; //int2 记录进位             for (i=str1.size()-1;i>=0;i--) {                 int1=(int(str1[i])-'0'+int(str2[i])-'0'+int2)%10;                 int2=(int(str1[i])-'0'+int(str2[i])-'0'+int2)/10;                 str=char(int1+'0')+str;             }             if (int2!=0) str=char(int2+'0')+str;         }     }     //运算后处理符号位     if ((sign==-1)&&(str[0]!='0')) str="-"+str;     return str; } string SUB_INT(string str1,string str2) {//高精度减法     int sign=1; //sign 为符号位     string str;     int i,j;     if (str2[0]=='-') {         str=ADD_INT(str1,str2.erase(0,1));     } else {         int res=compare(str1,str2);         if (res==0) return "0";         if (res<0) {             sign=-1;             string temp =str1;             str1=str2;             str2=temp;         }         string::size_type tempint;         tempint=str1.size()-str2.size();         for (i=str2.size()-1;i>=0;i--) {             if (str1[i+tempint]<str2[i]) {                 j=1;                 while (1) {//zhao4zhong1添加                     if (str1[i+tempint-j]=='0') {                         str1[i+tempint-j]='9';                         j++;                     } else {                         str1[i+tempint-j]=char(int(str1[i+tempint-j])-1);                         break;                     }                 }                 str=char(str1[i+tempint]-str2[i]+':')+str;             } else {                 str=char(str1[i+tempint]-str2[i]+'0')+str;             }         }         for (i=tempint-1;i>=0;i--) str=str1[i]+str;     }     //去除结果中多余的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str ="-"+str;     return str; } string MUL_INT(string str1,string str2) {//高精度乘法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         sign*=-1;         str1 =str1.erase(0,1);     }     if (str2[0]=='-') {         sign*=-1;         str2 =str2.erase(0,1);     }     int i,j;     string::size_type L1,L2;     L1=str1.size();     L2=str2.size();     for (i=L2-1;i>=0;i--) { //模拟手工乘法竖式         string tempstr;         int int1=0,int2=0,int3=int(str2[i])-'0';         if (int3!=0) {             for (j=1;j<=(int)(L2-1-i);j++) tempstr="0"+tempstr;             for (j=L1-1;j>=0;j--) {                 int1=(int3*(int(str1[j])-'0')+int2)%10;                 int2=(int3*(int(str1[j])-'0')+int2)/10;                 tempstr=char(int1+'0')+tempstr;             }             if (int2!=0) tempstr=char(int2+'0')+tempstr;         }         str=ADD_INT(str,tempstr);     }     //去除结果中的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str="-"+str;     return str; } string DIVIDE_INT(string str1,string str2,int flag) {//高精度除法。flag==1时,返回商; flag==0时,返回余数     string quotient,residue; //定义商和余数     int sign1=1,sign2=1;     if (str2 == "0") {  //判断除数是否为0         quotient= "ERROR!";         residue = "ERROR!";         if (flag==1) return quotient;         else         return residue ;     }     if (str1=="0") { //判断被除数是否为0         quotient="0";         residue ="0";     }     if (str1[0]=='-') {         str1   = str1.erase(0,1);         sign1 *= -1;         sign2  = -1;     }     if (str2[0]=='-') {         str2   = str2.erase(0,1);         sign1 *= -1;     }     int res=compare(str1,str2);     if (res<0) {         quotient="0";         residue =str1;     } else if (res == 0) {         quotient="1";         residue ="0";     } else {         string::size_type L1,L2;         L1=str1.size();         L2=str2.size();         string tempstr;         tempstr.append(str1,0,L2-1);         for (int i=L2-1;i<L1;i++) { //模拟手工除法竖式             tempstr=tempstr+str1[i];             tempstr.erase(0,tempstr.find_first_not_of('0'));//zhao4zhong1添加             if (tempstr.empty()) tempstr="0";//zhao4zhong1添加             for (char ch='9';ch>='0';ch--) { //试商                 string str;                 str=str+ch;                 if (compare(MUL_INT(str2,str),tempstr)<=0) {                     quotient=quotient+ch;                     tempstr =SUB_INT(tempstr,MUL_INT(str2,str));                     break;                 }             }         }         residue=tempstr;     }     //去除结果中的前导0     quotient.erase(0,quotient.find_first_not_of('0'));     if (quotient.empty()) quotient="0";     if ((sign1==-1)&&(quotient[0]!='0')) quotient="-"+quotient;     if ((sign2==-1)&&(residue [0]!='0')) residue ="-"+residue ;     if (flag==1) return quotient;     else         return residue ; } string DIV_INT(string str1,string str2) {//高精度除法,返回商     return DIVIDE_INT(str1,str2,1); } string MOD_INT(string str1,string str2) {//高精度除法,返回余数     return DIVIDE_INT(str1,str2,0); } int main() {     char ch;     string s1,s2,res;      while (cin>>s1>>ch>>s2) {         switch (ch) {             case '+':res=ADD_INT(s1,s2);break;             case '-':res=SUB_INT(s1,s2);break;             case '*':res=MUL_INT(s1,s2);break;             case '/':res=DIV_INT(s1,s2);break;             case '%':res=MOD_INT(s1,s2);break;             default :                   break;         }         cout<<res<<endl;     }     return(0); }

user: user-5
content: #include<stdio.h> #include<math.h> int main() {     unsigned long long n;     unsigned long long =0ull;     scanf("%llu",&n);     while(1ull<n)     {         if(n%2ull==1ull)         {             n=3ull*n+1ull;             n/=2ull;         }         else         {             n=n/2ull;         }         count++;         if(n==1ull) break;     }     printf("%llu\n",count);      return 0; }

user: user-0
content: 引用 3 楼 lm_whales 的回复:n =3*n+1;     n/=2 ; 改成             n = n+ (n+1)/2;   [quote=引用 楼主 zhang5476499 的回复:] 3n+1问题是一个简单有趣而又没有解决的数学问题。这个问题是由L. Collatz在1937年提出的。克拉兹问题（Collatz problem）也被叫做hailstone问题、3n+1问题、Hasse算法问题、Kakutani算法问题、Thwaites猜想或者Ulam问题。 问题如下： （1）输入一个正整数n； （2）如果n=1则结束； （3）如果n是奇数，则n变为3n+1，否则n变为n/2； （4）转入第（2）步。    #include<stdio.h> #include<math.h> int main() { 	int n; 	int count=0; 	scanf("%d",&n); 	while(1<n) 	{ 		if(n%2==1) 		{ 			n=3*n+1; 			n/=2; 		} 		else 		{ 			n=n/2; 		} 		count++; 		if(n==1) break; 	} 	printf("%d\n",count);  	return 0; } 刘汝佳的书上就写着：因为n为奇数时候3n+1一定是偶数，下一步将其立刻除以2.如果将将两次操作一起做，可以在一定程度上缓解这个问题。我就是这么做的，但是输出987654321时候还是溢出拉。[/quote]改了，还是溢出。按照你的代码，计数器count要进行修改。代码如下； #include<stdio.h> #include<math.h> int main() { 	int n; 	int count=0; 	scanf("%d",&n); 	while(1<n) 	{ 		if(n%2==1) 		{ 			n =(3*n+1)/2; 			count++; 			count++; 		} 		else 		{ 			n=n/2; 			count++; 		} 		if(n==1) break; 	} 	printf("%d\n",count);  	return 0; }

user: user-0
content: 引用 1 楼 zhao4zhong1 的回复:#include<stdio.h> #include<math.h> int main() {     unsigned __int64 n;     unsigned __int count=0ui64;     scanf("%I64u",&n);     while(1ui64<n)     {         if(n%2ui64==1ui64)         {             n=3ui64*n+1ui64;             n/=2ui64;         }         else         {             n=n/2ui64;         }         count++;         if(n==1ui64) break;     }     printf("%I64u\n",count);       return 0; } 赵老师，你的代码，目前超出我的范围，不过没关系，以后再慢慢看。

user: user-1
content: n =3*n+1;     n/=2 ; 改成             n = n+ (n+1)/2;   引用 楼主 zhang5476499 的回复:3n+1问题是一个简单有趣而又没有解决的数学问题。这个问题是由L. Collatz在1937年提出的。克拉兹问题（Collatz problem）也被叫做hailstone问题、3n+1问题、Hasse算法问题、Kakutani算法问题、Thwaites猜想或者Ulam问题。 问题如下： （1）输入一个正整数n； （2）如果n=1则结束； （3）如果n是奇数，则n变为3n+1，否则n变为n/2； （4）转入第（2）步。    #include<stdio.h> #include<math.h> int main() { 	int n; 	int count=0; 	scanf("%d",&n); 	while(1<n) 	{ 		if(n%2==1) 		{ 			n=3*n+1; 			n/=2; 		} 		else 		{ 			n=n/2; 		} 		count++; 		if(n==1) break; 	} 	printf("%d\n",count);  	return 0; } 刘汝佳的书上就写着：因为n为奇数时候3n+1一定是偶数，下一步将其立刻除以2.如果将将两次操作一起做，可以在一定程度上缓解这个问题。我就是这么做的，但是输出987654321时候还是溢出拉。

user: user-6
content: 引用 1 楼 zhao4zhong1 的回复:#include<stdio.h> #include<math.h> int main() {     unsigned __int64 n;     unsigned __int count=0ui64;     scanf("%I64u",&n);     while(1ui64<n)     {         if(n%2ui64==1ui64)         {             n=3ui64*n+1ui64;             n/=2ui64;         }         else         {             n=n/2ui64;         }         count++;         if(n==1ui64) break;     }     printf("%I64u\n",count);       return 0; }  ++

user: user-5
content: #include<stdio.h> #include<math.h> int main() {     unsigned __int64 n;     unsigned __int count=0ui64;     scanf("%I64u",&n);     while(1ui64<n)     {         if(n%2ui64==1ui64)         {             n=3ui64*n+1ui64;             n/=2ui64;         }         else         {             n=n/2ui64;         }         count++;         if(n==1ui64) break;     }     printf("%I64u\n",count);       return 0; }