自守数问题中的精度缺失问题

首先给出正确代码

法一,将数字各项进行比对

#include<stdio.h>
int main()
{
    
    long long int i,m,n;
    printf("0");
    for(i=1;i<200000;i++){
        n=i*i;
        m=i;
        while(m>0){
			 if(m%10!=n%10) break;
			    m/=10;
			    n/=10;
			 if(m==0) printf(" %d",i);        
		}
        
    }
    return 0;
}

法二:将数字整体进行比对(取余运算的灵活运用)

#include<stdio.h>
int main()
{
    
    long long int i,m,n;
    printf("0");
    for(i=1;i<200000;i++){
    	n=i*i;
       //确定取余的位数
       for(m=10;;m*=10){
	   	if(i<m) break;
	   } 
	   //判断i是否为自守数
	   if(i==(n%m)) printf(" %lld",i);
	   
    }
    return 0;
}

明显,第二种方法的代码更简洁,但是不好想,因为大家对比数字一般都是先把各位数取出来,然后再求和对比或者各位数字逐一对比。


不知道大家发现没,在这里的三个变量均定义为了long long int型,为什么要这么做呢?

仔细观察,n=i*i,如果i已经是个五位数,如果n是int型,那么很有可能n会溢出;

那我的i还是可以为int型呀,毕竟是200000以内。

但是i*i的结果还是会保存为int型,把这个int型的值赋给n,就算n是个long long int,也还是会精度不够。

所以,这里统一把i、m、n令为long long int,这样可以避免算术运算导致的精度缺失。

当然,还有一种做法,就是在n=i*i时进行强制类型转换,变成n=(long long int)i*i,这样也不会造成精度缺失。

当前几项能正确打印,后几项高位数字无法打印,那就要考虑是不是变量定义范围过小的问题了。

solved

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值