数的合成指将多个数字合成一个整数,比如将9、5、2、7合成9527。本文主要讨论的是整数的合成,附带提一下字符型数的合成。
一、整数的合成
整数合成指的是输入的数字和输出的整数都是以数的形式(即数据类型全部为int型)存储,而不用字符串。
有两种算法:
1.位值法(看似简单实则复杂低效的算法)
这种算法其实我们都很熟悉,造型是这样的:9*1000+5*100+2*10+7=9527。
只是它的名字可能我们比较陌生。
“位值法”(Positional Value Algorithm)中的位就是位置,值就是数值,即数字在其所在位置上的值,比如9在千位这个位置的位值是9000。这暗示此记数法的最大特点在于把数的“位置“作为衡量数大小的参数,即每个数字在不同的位置代表的权重是不一样的。也因此,它又被称为“位置记数法”(Positional Notation System)。
在这种记数法中,一个数的大小用一组有顺序的数字来表示,数的大小既取决于数字的值,也取决于数字的位置。
用公式来表示:数=∑数字*位置权重。上面算式中的1000、100、10、1就是权重(1没有显式写出),或者叫位权;9、5、2、7被称为因子或乘数。
这种我们今天想当然的记数法并不是所有记数法都采用的,比如罗马记数法就不属于位值法,因为它不遵循“位置决定值”的原则。
为什么说这种算法比较低效呢?
如果已知这个数的位数,此算法并不低效,直接套公式就行了。比如将3、2、7结合成整数327就可以用很简单的代码:
#include <stdio.h>
int main(){
int num, units, tens, hundreds;
scanf("%d%d%d", &hundreds, &tens, &units);
num = hundreds*100 + tens*10 + units*1;
printf("%d\n", num);
return 0;
}
或者更复杂一点,输入位数n及每个数字,输出合成的数,代码如下:
#include<stdio.h>
#include<math.h>
int main(){
int n, digit, num=0;
scanf("%d", &n);
int mod=pow(10, n-1); //计算权重
for(int i=n; i>0; i--){
scanf("%d", &digit);
num += digit * mod;
mod /= 10;
}
printf("%d\n", num);
return 0;
}
关键是如果不知道位数n,就要先求出这个数是几位数,因此降低了效率。比如连续输入多位用空格隔开的数字,当结束输入时,输出这些数字合成的数。这时候就要增加一个计数器来统计总共输入了多少个数字。因为数字个数输入完毕才能求出,因此还要用数组存储输入的每个数字。代码如下:
#include<stdio.h>
#include<math.h>
int main(){
int n=0, digit[100], num=0, mod=1;
//输入多位数字
while(scanf("%d", &digit[n])==1){
n++;
}
//从最后一位数字向前遍历求num
for(int i=n-1; i>=0; i--){
num += digit[i] * mod;
mod *= 10;
}
printf("%d\n", num);
return 0;
}
注意此程序运行时只按回车键并不能结束输入,需要按CTRL+Z。
2.连乘加法(看似复杂实则简单高效的算法)
这种算法的造型看起来就比较复杂了:((9*10+5)*10+2)*10+7 =9527。
这个算式本质上是与位值法相同的,如果把括号去掉,就和位值法一样。
但是,它的算法却完全不同。
换一下造型,就变一种思想。
“连乘加法”是老金自己取的名,之所以叫这个名,是因为这种算法通过连续地乘以10(即向左移动数字)和加上下一位的数字来构建整个数。它本质上是从最高位开始计算的,每增加一位数,就用原数乘以10加上新增加的数,就能得到合成后的数。这种算法的原理在于任何一个整数都能分成两部分:最低位和其他位,于是这个数就可以表示为其他位乘10+最低位。比如ab=a*10+b,abcde=abcd*10+e。
位值法和连乘加法最大的不同在于:位值法是从右向左(低位向高位)计算的,它将一个数看成不断向左增加最高位的数,权重有n个;连乘加法是从左向右(高位向低位)计算的,它将一个数看成不断向右增加个位的数,权重只有两个(10和1);
正因为只有两个权重,使用连乘加法能达到神奇的效果:不用计算位数,也不用数组,核心代码只有一行,就能非常简单地实现数的合成。
代码如下:
#include<stdio.h>
#include<math.h>
int main(){
int digit, num=0;
while(scanf("%d", &digit)==1){
num = num*10+digit;
}
printf("%d\n", num);
return 0;
}
是不是非常简单呢?
需要说明的是,无论位值法还是连乘加法,都属于数学运算方法,这种方法都要注意一个问题:整数溢出(数值超过数据类型所能表示的最大值)。
二、字符型数的合成
为彻底避免整数溢出问题,就要将输入的数变成字符,输出的数变成字符串。这时问题就简单了,只需要把字符逐个保存到一个字符数组中再加一个’\0’即可。代码如下:
#include<stdio.h>
int main(){
char c, str[100];
int i=0;
while(scanf(" %c", &c)==1){
str[i++]=c;
}
str[i]='\0';
printf("%s\n", str);
return 0;
}
但是这种方式也要考虑一个问题,就是数组的空间要足够大。另外,实测需要按两次CTRL+Z才能结束输入,不知道为什么?感觉应该是编译器有BUG吧。
最后再附带一句,也有可能要求输入整数(单个数字),输出字符串,或者相反,输入字符输出整数(多位数)。这其实也很简单,涉及到整数和字符的转换,只需要利用数的ASCII码值与数值的对应关系(char型数-48=int型数)即可。
标签:10,高效,数字,int,合成,digit,算法,num,include From: https://blog.csdn.net/jjmhx/article/details/141224654