zoukankan      html  css  js  c++  java
  • 1060. Are They Equal (25)

    题目如下:

    If a machine can save only 3 significant digits, the float numbers 12300 and 12358.9 are considered equal since they are both saved as 0.123*105 with simple chopping. Now given the number of significant digits on a machine and two float numbers, you are supposed to tell if they are treated equal in that machine.

    Input Specification:

    Each input file contains one test case which gives three numbers N, A and B, where N (<100) is the number of significant digits, and A and B are the two float numbers to be compared. Each float number is non-negative, no greater than 10100, and that its total digit number is less than 100.

    Output Specification:

    For each test case, print in a line "YES" if the two numbers are treated equal, and then the number in the standard form "0.d1...dN*10^k" (d1>0 unless the number is 0); or "NO" if they are not treated equal, and then the two numbers in their standard form. All the terms must be separated by a space, with no extra space at the end of a line.

    Note: Simple chopping is assumed without rounding.

    Sample Input 1:
    3 12300 12358.9
    
    Sample Output 1:
    YES 0.123*10^5
    
    Sample Input 2:
    3 120 128
    
    Sample Output 2:
    NO 0.120*10^3 0.128*10^3

    这个题目的难点在于要处理的数不一定都是大于1的,还可能出现0.015这样的数字,我之前的代码只能处理大于1的情况,后来参考了小5555的代码,发现可以用两个游标指示小数点和第一个非0数的位置,然后判断二者的位置关系来判断数的值。

    首先定义一个结构体,来存储基数和次方:

    struct result{
    	char d[MAX]; // 0.xxx部分
    	int k; // 10的k次方
    };

    然后设计一个函数,对于输入的数字(存储在char*内)数组进行遍历。

    遍历时定义firstPos记录第一个非0数,pointPos记录小数点位置。

    需要注意以下问题:

    ①题目的case似乎出现了00123.45这种坑爹的情况,因此要处理无效的0,也就说开头出现的0是不能要的,只有碰到第一个非0才记录firstPos。

    ②对于题目给定的精度,如果输入的数字位数不够,要补0,在结尾处还要补使得字符串可靠结束。

    ③处理完毕后,对于firstPos和pointPos做比较,如果前者小,说明是大于1的数,pointPos - firstPos即为10的几次方;如果后者小,说明是小数,应该用firstPos - pointPos + 1,+1是因为firstPos越过了小数点,而小数点不能算作一位,注意的是这个次方是负值。

    ④比较相等时,如果基数部分一致、次方也一致,才算相等。

    代码如下:

    #include <stdio.h>
    #include <string.h>
    #define MAX 110
    struct result{
    	char d[MAX]; // 0.xxx部分
    	int k; // 10的k次方
    };
    
    result getResult(char *a, int n){
    	result r;
    	int firstPos = -1;
    	int pointPos = -1;
    	int index = 0;
    	int i;
    	for (i = 0; a[i]; i++){
    		if (a[i] == '.'){
    			pointPos = i;
    			continue;
    		}
    		else if (a[i] == '0' && firstPos == -1) // 不能以0开头,否则忽略
    			continue;
    		else{
    			if (firstPos == -1)
    				firstPos = i; // 第一个非0数字的位置
    			if (index < n)
    			{
    				if (index < strlen(a))
    					r.d[index++] = a[i]; // 对于特定的精度,有数字则填入相应数字,没有则补0
    				else
    					r.d[index++] = '0';
    			}
    		}
    	}
    	r.d[index] = 0; // 在数字结尾加,防止越界
    	if (pointPos == -1)
    		pointPos = i; // 如果没有找到小数点,则小数点在最后,这是个纯整数
    	if (pointPos - firstPos < 0) // 判断小数点与第一个非0数字的位置关系,计算10的几次方
    		r.k = - (firstPos - pointPos - 1); // 负次方,例如0.015,pointPos = 1, firstPos = 3, 3 - 1 - 1 = 1, -1是因为多算了小数点进去,0.15*10^-1
    	else
    		r.k = pointPos - firstPos; // 正次方,例如21.25,pointPos = 2,firstPos = 0,2-0=2,0.2125*10^2
    	if (index == 0){ // 如果index = 0,代表值为0,则每一位都写0,再加
    		int i;
    		for (i = 0; i != n; i++)
    			r.d[i] = '0';
    		r.d[i] = 0;
    		r.k = 0;
    	}
    	return r;
    }
    
    int main(){
    	int n;
    	char a[MAX], b[MAX];
    	scanf("%d%s%s", &n, a, b);
    	result r1 = getResult(a, n);
    	result r2 = getResult(b, n);
    	if (strcmp(r1.d, r2.d) == 0 && r1.k == r2.k)
    		printf("YES 0.%s*10^%d
    ", r1.d, r1.k);
    	else
    		printf("NO 0.%s*10^%d 0.%s*10^%d
    ", r1.d, r1.k, r2.d, r2.k);
    	return 0;
    }
    



  • 相关阅读:
    Mac 虚拟机VMware Fusion显示内部错误的解决方法
    Linux系统中的引导过程与服务控制
    linux系统中如何删除lvm分区
    Linux命令下: LVM逻辑卷配置过程详解(创建,增加,减少,删除,卸载)
    解决:rm: 无法删除"tomcat": 设备或资源忙
    LVM操作过程
    Linux命令下进行硬盘挂载、分区、删除分区,格式化,卸载方法
    finger 命令查询用户名、主目录、停滞时间、登录时间
    【MySQL】MySQL5.7传统复制切换为GTID复制
    深入理解MySQL系列之锁
  • 原文地址:https://www.cnblogs.com/aiwz/p/6154105.html
Copyright © 2011-2022 走看看