C语言(11)--回文日、确定等式、fflush(stdin)、将十进制数转换成n进制数、二分法解方程

1.回文日

2011年11月02日是一个回文日:2011 1102,请列出本世纪还有多少个回文日?


当年份确定后,如2015年,就看20155102能否构成一个合法的日期,其中51部分是月,02部分是日。显然,由2015就不能得出一个回文日。
再如,当年份取2090年时,20900902,由2090可以构造出一个回文日来。
用年份循环并判断,而不是罗列所有的日期,显然效率上更好。

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int year,month,day,date,y;
    int is_cycle;//用于标识判断结果
    int count=0;
    for(year=2015;year<2100;year++)
    {
        is_cycle=0;
        month=year%100;//若原月份前两位是回文日,原年份后两位对应月
        month=month/10+month%10*10;//把月倒过来为真正月份
        day=year/100;//若是回文日,原年份前两位对应日
        day=day/10+day%10*10;//把日倒过来为真正日
        switch(month)
        {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                if(day<=31){
                    is_cycle=1;
                }
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                if(day<=30){
                    is_cycle=1;
                }
                break;
            case 2:
                if((year%4==0&&year%100!=0)||year%400==0){//闰年
                    if(day<=29){
                        is_cycle=1;
                    }
                }
                else{
                    if(day<=28){
                        is_cycle=1;
                    }
                }
                break;
            default:
                continue;
        }
        y=year;
        if(is_cycle){
            date=y;
            while(y>0){
                date=date*10+y%10;
                y/=10;
            }
            printf("%d\n",date);
            count++;
        }
    }
    printf("共有%d个回文日.\n",count);
    return 0;
}


2.确定等式

有等式[※×(※3+※)]^2=8※※9,其中※处为1个数字,滴上了墨水无法辨认。请编程找出※表示哪个数字。

代码:【遍历】

#include <stdio.h>
#include <math.h>

int main()
{
    int a,b,c,temp,left;
    for(a=1;a<=9;a++){
        for(b=1;b<=9;b++){
            for(c=0;c<=9;c++){
               temp=a*((b*10+3)+c);
               left=pow(temp,2);
               if(left/1000==8&&left%10==9){
                    printf("%d %d %d %d %d\n",a,b,c,left/100-left/1000*10,left/10-left/100*10);
               }
            }
        }
    }
    return 0;
}

需要注意的是在调用pow函数时,要求参数类型为float,返回值类型也为float,因此容易造成精度损失。

单步执行时当temp=13,15,20,21,22,23..时(起始13)对应的left都少1,而其他数(14,16,17,18,...)都正常。

所以应将

left=pow(temp,2);

改为 :

left=temp*temp;
//或者
left=(int)(0.1+pow(temp,2));

错误的运行:


正确运行:



3.fflush(stdin):清除键盘缓存区

(缓存区:在输入输出时,系统分配一段内存区域,将输入输出的内容放在这片区域)

fflush:函数名;stdin代表标准输入(键盘)


有如下程序常用于重复性工作:

#include<stdio.h>
void dosomething(int *p);
int main( )
{
    char choice='y';
    int n=0;
    while(choice!='N' && choice!='n')
    {
        dosomething(&n);
        printf("按 N 退出,其他键继续....");
        scanf("%c", &choice); //用choice=getchar();也一样
    }
    return 0;
}


void dosomething(int *p) //完成特定的业务
{
    *p+=1;  //本例中传地址, *p即n
    printf("第%d次完成业务!\n", *p);
}


尝试运行如下:



输入:666<回车>

发现运行异常。这是因为缓存区中保存了666'\n'[回车字符],所以第三次时直接的choice用缓存区中的第二个6,第四次choice用缓存区中的第三个6,第五次choice用缓存区中的'\n',以至于多出来了:



正确的源代码应该在输入前先清除缓存区:

#include<stdio.h>
void dosomething(int *p);
int main( )
{
    char choice='y';
    int n=0;
    while(choice!='N' && choice!='n')
    {
        dosomething(&n);
        printf("按 N 退出,其他键继续....");
        fflush(stdin);//读入字符前,常要清空“输入缓存区”
        scanf("%c", &choice); //用choice=getchar();也一样
    }
    return 0;
}

void dosomething(int *p) //完成特定的业务
{
    *p+=1;  //本例中传地址, *p即n
    printf("第%d次完成业务!\n", *p);
}


这样运行就正常了:


4.将十进制数转换成n进制数

#include <stdio.h>
#include <stdlib.h>
//除以n取余数保存在数组中,然后将数组从后往前输出,因为后面是高位
int main()
{
    int n,b,i=0,j,a[20];
    scanf("%d",&n);
    scanf("%d",&b);
    while(b)
    {
        a[i++]=b%n;
        b/=n;
    }
    i--;
    for(j=i;j>=0;j--)
    {
        printf("%d",a[j]);
    }
    printf("\n");
    return 0;
}

运行结果:



5.二分法解方程

二分法是在计算机科学中很重要的一种方法,用于查找产生二分查找算法,还可以用在很多场合。
  可以用二分法解方程。
  对于区间[a,b]上连续不断且f(a)·f(b)<0的函数y=f(x),通过不断地把函数f(x)的零点所在的区间一分为二,使区间的两个端点逐步逼近零点,进而得到零点近似值的方法叫二分法。
  假设要求方程f(x)=0的解,给定精确度ξ。其算法是:

  • 1 确定区间[a,b],验证f(a)·f(b)<0
  • 2 求区间(a,b)的中点c
  • 3 判断
(1) 若f(a)·f(c)<0,则令b=c;
(2) 若f(c)·f(b)<0,则令a=c.

  • 4 判断f(c)是否达到精确度ξ:即若┃f(c)┃<ξ,则x=c就是使f(x)接近零点的近似值,否则重复2-4.
请按照上面的算法,编程序求解方程f(x)=2x^3-5x^2+3x-6=0,要求精确到0.00001

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double f(double x);
int main()
{
    double a,b,c;
    do{
        printf("请输入一个范围:");
        scanf("%lf %lf",&a,&b);
    }while(f(a)*f(b)>0);
    printf("该方程在%lf-%lf之间有一解为",a,b);
    do{
        c=(a+b)/2;
        if(f(a)*f(c)<0)
            b=c;
        else
            a=c;
    }while(fabs(f(c))>1e-5);
    printf("%lf\n",c);
    return 0;
}

double f(double x)
{
    return (3*x*x*x-5*x*x+3*x-6);
}

运行:


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值