首页 > 试题广场 >

Are They Equal (25)

[编程题]Are They Equal (25)
  • 热度指数:8399 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
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.

输入描述:
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.


输出描述:
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.
示例1

输入

3 12300 12358.9

输出

YES 0.123*10^5
#include<iostream>
#include<iomanip>
#include<string>
using namespace std;

int main() {
	char a[101];
	char b[101];
	int k;
	cin >> k >> a >> b;
	string s1 = a;
	string s2 = b;
	string s3, s4;
    //w1,w2为小数点位置,w3,w4为第一位有效数字位置,e1,e2为指数
	int w1, w2, w3, w4, e1, e2;
	w1 = s1.find_first_of(".");
	w2 = s2.find_first_of(".");
    //如果没有小数点,则小数点位置在末尾
	if (w1 == -1) w1 = s1.length();
	if (w2 == -1) w2 = s2.length();
    //字符串去除小数点
	s1 = s1.erase(w1, 1);
	s2 = s2.erase(w2, 1);
	w3 = s1.find_first_not_of("0");
	w4 = s2.find_first_not_of("0");
    //计算指数
	e1 = w1 - w3;
	e2 = w2 - w4;
    //如果没有有效数字,即字符串除小数点外全是0,则有效数字为0,指数为0
    //w3可以指定为任意小于字符串长度且大于-1的整数,此处指定为0
	if (w3 == -1) {
		w3 = 0;
		e1 = 0;
	}
	if (w4 == -1) {
		w4 = 0;
		e2 = 0;
	}
    //输出的有效数字部分,从第一位有效数字开始,截取k位
	s3 = s1.substr(w3, k);
	s4 = s2.substr(w4, k);
    //若截取的有效数字部分不足k位,b为True,反之为False
	bool b1 = k > s3.length();
	bool b2 = k > s4.length();
    //不足部分后面补零
	cout.fill('0');
	if (e1 == e2 && s3.compare(s4) == 0) {
		if (b1) {
			cout << "YES" << " 0." << s3 << setw(k - s3.length()) << 0 << "*10^" << e1 << endl;
		}
		else cout << "YES" << " 0." << s3 << "*10^" << e1 << endl;
	}
	else {
		if (b1) cout << "NO" << " 0." << s3 << setw(k - s3.length()) << 0 << "*10^" << e1;
		else cout << "NO" << " 0." << s3 << "*10^" << e1;
		if (b2) cout << " 0." << s4 << setw(k - s4.length()) << 0 << "*10^" << e2 << endl;
		else cout << " 0." << s4 << "*10^" << e2 << endl;
	}
	return 0;
}

发表于 2019-09-17 10:47:42 回复(0)
//原来小数点和第一个有效数字位的位置才是这道题的关键,而不是分析各种可能情况的细节!
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
string get_standard(string f, unsigned n) {
	string ret;
	string zero(n, '0');
	zero = "0." + zero + "*10^0";
	auto point = f.find('.');
	auto validate = f.find_first_not_of("0.");
	int expo;
	if (validate == string::npos) {
		ret = zero;
		return ret;
	}
	if (point == string::npos&&validate != string::npos)
		expo = f.size() - validate;
	else {
		expo = point - validate;
		if (expo < 0)
			expo += 1;
	}
	ret = "0.";
	for (size_t i = validate;ret.size()<n+2;++i) {
		if (i < f.size()) {
			if (f[i] != '.')
				ret.push_back(f[i]);
		}
		else
			ret.push_back('0');
	}
	ret = ret + "*10^";
	stringstream ss;
	ss << expo;
	string temp;
	ss >> temp;
	ret += temp;
	return ret;
}
int main() {
	//测试get_standard函数
/*
	string ss[] = { "0","0.0000","000005","0.00003","0.12345","1.2","1.23456","123456.34234" };
	for (int i = 0;i < 8;++i) {
		cout << get_standard(ss[i], 3) << endl;
	}
*/
	int N;
	while (cin >> N) {
		string f1, f2;
		cin >> f1 >> f2;
		string standard1 = get_standard(f1,N);
		string standard2 = get_standard(f2,N);
		if (standard1 == standard2) {
			cout << "YES " << standard1 << endl;
		}
		else {
			cout << "NO " << standard1 << " " << standard2 << endl;
		}
	}
}

发表于 2015-11-30 16:12:10 回复(0)
//关键:把浮点数按字符串考虑,标记小数点位置与首个非零位
#include <iostream>
#include <string>
using namespace std;

#define MAX 1000
int N; string A, B, stanA, stanB;

int transfer(string X, string& stanX) {
	int dot = 0;
	while (dot < X.size() && X[dot] != '.')++dot;

	int nz = 0;
	while (nz < X.size() && (X[nz] == '0' || nz == dot))++nz;
	if (nz == X.size())nz = dot;

	int k = (dot >= nz) ? dot - nz : dot - nz + 1;

	stanX += "0.";
	for (int i = 0; i < N; ++i) {
		if (X[i + nz] == '.')++N;
		else if (i + nz < X.size())stanX += X[i + nz];
		else stanX += '0';
	}
	return k;
}

int main()
{
	cin >> N >> A >> B;
	int k1 = transfer(A, stanA);
	int k2 = transfer(B, stanB);
	if (stanA == stanB && k1 == k2)
		cout << "YES " << stanA << "*10^" << k1;
	else {
		cout << "NO ";
		cout << stanA << "*10^" << k1 << " ";
		cout << stanB << "*10^" << k2;
	}
	return 0;
}

编辑于 2021-01-19 07:33:32 回复(0)
#include<bits/stdc++.h>
using namespace std;
int n;
string change(string s, int &ex){
    int pos1=0,pos2=0;//pos1为小数点位置,po2为第一个非零数字的位置
    while(pos1<s.size()&&s[pos1]!='.') pos1++;
    while(pos2<s.size()&&(s[pos2]=='.'||s[pos2]=='0')) pos2++;
    if(pos1>pos2) ex=pos1-pos2;
    else ex=pos1-pos2+1;
    if(pos2==s.size()) ex=0;
    string ans(n,'0');  //ans存储小数位,初始化为n个0
    for(int i=0,j=pos2;i<n&&j<s.size();j++){
        if(s[j]!='.') ans[i++]=s[j]; //注意可能包含小数点的情况
    }
    return ans;
}
int main(){
    string a,b;
    cin>>n>>a>>b;
    int exa=0,exb=0;
    string s1=change(a,exa),s2=change(b,exb);
    if(s1==s2&&exa==exb) printf("YES 0.%s*10^%d",s1.c_str(),exa);
    else printf("NO 0.%s*10^%d 0.%s*10^%d",s1.c_str(),exa,s2.c_str(),exb);
    return 0;
}

题目的意思就是将数字转换给定位数的“科学计数法”——这里的科学计数法与数学中的科学计数法有所不用,但思路相同。结果必须是给定格式,即小数位数必须为给定位数,不足补零。
1. 注意:
(1)严格按照题目给定的输出格式,即即使是10^0 或 10^1也要输出;
(2)k是指数,与n无关,只与输入数字的数量级有关;
(3)注意指数有正负之分。如果输入的数为0,不管是0.0, 0.000...的指数都为0

2. 小技巧:
(1)即使可能输入字符串中不存在.,也可以返回字符串末尾的后一个位置(实际上小数点也就是在那),所以才将其初始化为s.size()。

(2)求出了指数之后,最关键的地方就是求小数部分。由于小数位数为n,因此可以一开始初始化为长度为n的字符串,且由于不足n个数字也得补0,那么可以在初始化的时候直接将小数部分全部初始化为0。

更多题解参见我的博客:https://blog.csdn.net/weixin_43590232/category_9685861.html

编辑于 2020-03-03 15:18:00 回复(0)
对这道破题,我要好好写一下解答思路
import math as t
a = input().split()
try:m = t.log(eval(a[1]),10)
except:m = 0;
try:n = t.log(eval(a[2]),10)
except:n = 0
m = int(m) - 1 if m < 0 else int(m)
n = int(n) - 1 if n < 0 else int(n)
a[1] = a[1].replace('.','')
a[2] = a[2].replace('.','')
c = '{:0<' + str(a[0]) + '}'
for i in range(len(a[1])):
    if a[1][i] != '0':
        a[1] = '0.' + c.format(int(a[1][i:i + int(a[0])])) + '*10^' + str(m + 1)
        break
else:
    a[1] = '0.' + c.format(int(a[1][i:i + int(a[0])])) + '*10^' + str(m)
for i in range(len(a[2])):
    if a[2][i] != '0':
        a[2] = '0.' + c.format(int(a[2][i:i + int(a[0])])) + '*10^' + str(n + 1)
        break
else:
    a[2] = '0.' + c.format(int(a[2][i:i + int(a[0])])) + '*10^' + str(n)
if a[1] == a[2]:
    print('YES',a[1])
else:
    print('NO',a[1],a[2]) 
首先,获取两数的以10为底的对数的整数值(由于处理近似的机制限制,负数值要减少1),如果两数有值为0的话就直接返回0(牛客第一个用例);
其次,既然记录了两数的对数值就知道其大小,因此可去掉数中的小数点和非有效数字0,得到两个裸数;
再次,根据题目要求输出的格式,转化成:“0.” + “裸数(根据要求有效位数,可能只输出数前方一部分,也可能不够要在其后补0)” + “*10^” + “对数值 + 1”的结果;
最后,比较两结果是否相等,然后再相应输出就行了。

切忌对两数进行运算,有精度影响。


编辑于 2020-02-19 20:38:44 回复(0)
#include <iostream>
#include <string>

using namespace std;

void Fun(string &s, string &b, int &e, int N)
{     int l = s.length();     int p = s.find('.');     if(p<0)         e = l;     else{         e = p;         s.erase(p,1);     }     int i=0;     l=s.length();     while(i<l)     {         if(s[0]=='0')         {             e--;             s.erase(0,1);         }else             break;         i++;     }     if(i==l)         e = 0;          b = "";     l = s.length();     for(int i=0;i<N;i++)     {         if(i<l)             b += s[i];         else             b += '0';     }
}

int main()
{     int N;     string s1,s2;     cin>>N>>s1>>s2;          string b1,b2;     int e1,e2;     Fun(s1, b1, e1, N);     Fun(s2, b2, e2, N);          if(b1==b2 && e1==e2)         cout<<"YES 0."<<b1<<"*10^"<<e1<<endl;     else{         cout<<"NO 0."<<b1<<"*10^"<<e1<<" 0."<<b2<<"*10^"<<e2<<endl;     }          return 0;
}

发表于 2018-02-25 01:09:41 回复(0)
#include<cstdio>//自己生撸百行代码!!!!!!!
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
string a;string b;
char as[105],bs[105]; 
int main(){
  int num=0,i=0,j=0,a0=0,b0=0;
  int ea=0,eb=0;
  scanf("%d",&num);
  cin>>a;cin>>b;
  //修正a和b字符串!!!!! 
  while(a[i]=='0'){
    a0++;
    i++;
}   a.erase(a.begin(),a.begin()+a0);
  while(b[j]=='0'){
    b0++;j++;
}  b.erase(b.begin(),b.begin()+b0);
//  cout<<a<<endl;cout<<b<<endl;;//中途测试a和b!! 
  //获得各自的数字! 
    if(a[0]=='.'){
      int ka=1;
      while(a[ka]=='0'){
      ea--;ka++;
      }
      if(ea+a.size()-1==0) ea=0;
    }
    else{
      i=0;
      while(a[i]!='.'&&i<a.size()){
        ea++;i++;
      }
    }
    if(b[0]=='.'){
      int kb=1;
      while(b[kb]=='0'){
      eb--;kb++;
      }
      if(eb+b.size()-1==0) 
        eb=0;
    }
    else{
      i=0;
      while(b[i]!='.'&&i<b.size()){
        eb++;i++;
      }
    }
//    printf("%d %d\n",ea,eb);//中途测试a和b的指数!!
    //取有效数字!!
    int jishu=0;i=0;
      if(a[0]=='.'){
      i=i-ea+1;
      while(i<a.size()&&jishu<num)
        as[jishu++]=a[i++];
      }
      else{
         jishu=0;
        while((a[i]>='0'&&a[i]<='9'&&jishu<num)||a[i]=='.') {
          if(a[i]=='.'){
          i++;
          continue;     }
          as[jishu++]=a[i++];
      }}
    if(jishu<num){
        for(j=jishu;j<num;j++) as[j]='0';
      }
      jishu=0;i=0; //开始取b的! 
      if(b[0]=='.'){
      i=i-eb+1;
      while(i<b.size()&&jishu<num)
        bs[jishu++]=b[i++];
      }
      else{
         jishu=0;
        while((b[i]>='0'&&b[i]<='9'&&jishu<num)||b[i]=='.') {
          if(b[i]=='.'){
              i++;
          continue;     }
          bs[jishu++]=b[i++];
      }}
    if(jishu<num){
        for(j=jishu;j<num;j++) bs[j]='0';
      }
//  printf("%s %s\n",as,bs);  //测试有效数字! 
    //正式输出! 
    int yy=0;
    if(ea==eb){
      for(i=0;i<num;i++){
        if(as[i]!=bs[i]){
        printf("NO 0.%s*10^%d 0.%s*10^%d\n",as,ea,bs,eb);
        return 0;}
          yy++;
      }
    } else
     printf("NO 0.%s*10^%d 0.%s*10^%d\n",as,ea,bs,eb);
        if(num==yy) printf("YES 0.%s*10^%d\n",as,ea); //此处一定要改成计数之后比较!! 
  return 0;
}
发表于 2018-01-14 00:51:14 回复(0)
import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		String a = format(in.next());
		String b = format(in.next());
		int ai = index(a);
		int bi = index(b);
		a = getResult(a, n, ai);
		b = getResult(b, n, bi);
		if(a.equals(b))
			System.out.print("YES"+a);
		else
			System.out.print("NO"+a+b);
	}
    private static String format(String s){//00000001这种特殊情况
		if(s.charAt(0)!='0')
			return s;
		int i = 1;
		for(;i<s.length();i++)
			if(s.charAt(i)!='0')
				break;
		if(i==1)
			return s;
		return s.substring(i);
	}
	private static String getResult(String s,int n,int index){
		char[] c = new char[n];
		int l = 0;
		int r = 0;
		int j = 0;
		for(int i = 0;i<s.length()&&j<n;i++){
			if(s.charAt(i)!='.'){
				if(j==0&&s.charAt(i)=='0')
					continue;
				if(j==0)
					r = i-1;
				c[j++] = s.charAt(i);
			}else if(s.charAt(i)=='.'){
				l = i;
			}
		}
		while(j<n)
			c[j++] = '0';
		int re = index;
		if(l-r<0)
			re = l-r;
		return " 0."+new String(c)+"*10^"+re;
	}
	private static int index(String s){
		int i = s.indexOf('.');
		if(i==-1)
			i = s.length();
		if(s.charAt(0)=='0')
			i = 0;
		return i;
	}
}

发表于 2016-07-18 23:34:26 回复(0)
啥头像
总体思路
       1.用字符串来处理
       2.分离出指数和底数(没有“0.”的底数)
       3.注意0.00的情况

代码如下:
#include <iostream>
#include <string>

using namespace std;

void getBaseExponents(string& str, string& base, int& exponents, int& N);

int main()
{
    // 读入数据
    int N; string str1, str2;
    cin >> N >> str1 >> str2;

    // 得到底数位(没有0.)和指数
    string base1, base2;
    int exponents1, exponents2;
    getBaseExponents(str1, base1, exponents1, N);
    getBaseExponents(str2, base2, exponents2, N);

    // 输出结果
    if(base1 == base2 && exponents1 == exponents2) {
        cout << "YES 0." << base1 << "*10^" << exponents1 << endl;
    } else {
        cout << "NO 0." << base1 << "*10^" << exponents1 \
            << " 0." << base2 << "*10^" << exponents2 << endl;
    }
    return 0;
}

void getBaseExponents(string& str, string& base, int& exponents, int& N)
{
    int length = str.length();
    // 是否有小数点,并得到指数位数
    int pos = str.find('.');
    if(pos < 0) {
        exponents = length;
    } else {
        exponents = pos;
        str.erase(pos, 1);
    }

    // 是否前面有0
    int i=0; length = str.length();
    for(; i<length; i++) {
        if(str[0] == '0') {
            exponents--;
            str.erase(0, 1);
        } else {
            break;
        }
    }
    if(length == i) {
        exponents = 0;
    }

    // 得到base
    base = ""; length = str.length();
    for(i=0; i<N; i++) {
        if(i<length) {
            base += str[i];
        } else {
            base += '0';
        }
    }
} 


发表于 2015-11-23 15:36:20 回复(0)
import java.util.Scanner;
import java.math.BigDecimal;

public class AreTheyEqual {
public static void main(String[] args) {
int num1, num2;
Scanner scan0 = new Scanner(System.in); 
int numwei = Integer.parseInt(scan0.nextLine());
Scanner scan1 = new Scanner(System.in); 
float f1 = Float.parseFloat(scan1.nextLine());
String str1 = String.valueOf(f1);
if (str1.indexOf(".") >= 0) {
int idx1 = str1.lastIndexOf(".");
String strNum1 = str1.substring(0, idx1);
num1 = strNum1.length();
}else {
num1 = str1.length();
}
BigDecimal b1 = new BigDecimal(f1/Math.pow(10,num1)); 
float re1 = b1.setScale(numwei,BigDecimal.ROUND_HALF_UP).floatValue();
Scanner scan2 = new Scanner(System.in);
float f2 = Float.parseFloat(scan2.nextLine());
String str2 = String.valueOf(f2);
if (str2.indexOf(".") >= 0) {
int idx2 = str2.lastIndexOf(".");
String strNum2 = str2.substring(0, idx2);
num2 = strNum2.length();
}else {
num2 = str2.length();
}
float r1 = (float)((f1 - f1 % Math.pow(10,numwei)) / Math.pow(10,numwei));
float r2 = (float)((f2 - f2 % Math.pow(10,numwei)) / Math.pow(10,numwei));
if ( r1 == r2 ) { 
System.out.println("true  "+ re1 + "*10^"+ num1 );
}
else
System.out.println("false");
System.exit(0);
}
}

编辑于 2015-11-17 20:10:11 回复(2)
    #include <iostream>
    #include <math.h>
    #include <string.h>
    #include <iomanip>
    using namespace std;
    typedef struct try1{
        int mark;
        int findp;
    };
    string a,b,c,d;
    int n;
    try1 getp(string a)
    {
        int x=a.find('.');
        bool pd=true;
        int mark;
        for (int i=0;i<a.length();i++)
            if ((a[i]!='0')&&(i!=x))
        {
            pd=false;
            mark=i;
            break;
        }
        try1 ans;
        if (pd)
        {
            ans.findp=0;
            ans.mark=0;
        }
        else
        if (x>a.length())
        {
            ans.findp=a.length();
            ans.mark=mark;
        }
            else
                {
                    ans.findp=x;
                    ans.mark=mark;
                }
        return ans;
    }
    int main()
    {
        cin>>n;
        cin>>a>>b;
        bool pd=true;
        try1 ansa=getp(a),ansb=getp(b);


        int tol=0;
        int mark=ansa.mark;
        //cout<<mark;
        while (tol<n)
        {
            if (mark>=a.length())
            {
                c=c+'0';
                tol++;
            }
            else
            if (a[mark]!='.')
            {
                c=c+a[mark];
                tol++;
            }
            mark++;
        }
        tol=0;
        mark=ansb.mark;
        while (tol<n)
        {
            if (mark>=b.length())
            {
                d=d+'0';
                tol++;
            }
            else
            if (b[mark]!='.')
            {
                d=d+b[mark];
                tol++;
            }
            mark++;
        }
        //cout<<c<<endl<<d<<endl;
        if (ansa.findp-ansa.mark==ansb.findp-ansb.mark)
        {
            if (c!=d) pd=false;
        }
        else pd=false;
        if (ansa.findp-ansa.mark<0) ansa.findp++;
        if (ansb.findp-ansb.mark<0) ansb.findp++;

        if (pd==true) cout<<"YES"<<" 0."<<c<<"*10^"<<ansa.findp-ansa.mark<<endl;
            else cout<<"NO"<<" 0."<<c<<"*10^"<<ansa.findp-ansa.mark<<" 0."<<d<<"*10^"<<ansb.findp-ansb.mark<<endl;
    }




算下小数点的位置和第一个有效数字的位置就好啦

发表于 2015-11-10 11:37:44 回复(1)
#include<bits/stdc++.h>
using namespace std;

int n;

string deal(string s,int & e) {
    int i;
    while(s.size()>0&&s[0]=='0') {
        s.erase(s.begin());
    }
    if(s[0]=='.') {
        s.erase(s.begin());
        while(s.size()>0&&s[0]=='0') {
            s.erase(s.begin());
            e--;
        }
    } else {
        while(i<s.size()&&s[i]!='.') {
            i++;
            e++;
        }
        if(s.size()>i){
            s.erase(s.begin()+i);
        }
    }
    if(s.size()==0) {
        e=0;
    }
    int num=0,k=0;
    string answer;
    while(num<n) {
        if(k<s.size()) {
            answer+=s[k++];
        }
        else{
            answer+='0';
        }
        num++;
    }
    return answer;
}

int main() {
    string s1,s2,s3,s4;
    int e1=0,e2=0;
    while(cin>>n>>s1>>s2) {
        s3=deal(s1,e1);
        s4=deal(s2,e2);
        if(s3==s4) {
            cout<<"YES 0."<<s3<<"*10^"<<e1<<endl;
        } else {
            cout<<"NO 0."<<s3<<"*10^"<<e1<<" 0."<<s4<<"*10^"<<e2<<endl;
        }
    }
    return 0;
}
发表于 2022-10-22 14:40:35 回复(1)
给大家一个测试用例,看看这个题有多坑。。。
用例输入为:99 0 0.000 用例输出为:YES 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000*10^0
发表于 2021-09-27 15:11:28 回复(0)


更多PAT甲级题解--acking-you.github.io

题目


OJ平台

题目分析

这道题有有点坑坑的,最开始的前情提要过于的晦涩,开始无故就说一个机器只能保存三个有效数字,结果没给出丝毫有用的信息总结!
我后面翻了下别人的题解,发现原来是这个题意:

给出两个数,问将它们写成保留N位小数的科学计数法后是否相等。如果相等,输出YES,输出他们的科学记数法表示方法。如果不相等输出NO,分别输出他们的科学计数法

好了,题意弄懂了,准备开始敲代码吧!

代码详解

得到科学计数法的指数大小

直接利用 '.'第一个非0有效数 的位置关系可以得到转换为科学计数法时的指数大小!

int get_len(string& s) {                                                    //@用于处理指数的大小
    int pos = s.find('.');
    int start = 0;
    while (start < s.size() && (s[start] == '0' || s[start] == '.'))start++;
    if (pos == string::npos)pos = s.size();
    if (start == s.size())return 0;         //全是0的情况
    if (pos > start)return pos - start;     //小数点在第一位有效数字后面
    return pos - start + 1;                 //小数点在第一位有效数字前面
}

取出N位有效数字(不够用0填补)

string get_str(string& s) {                                                 //@返回答案字符串
    string t = "";
    int n = N;
    int cnt = 0;
    int start = 0;
    while (start < s.size() && (s[start] == '0' || s[start] == '.'))start++;//处理前导0
    for (int i = start; i < s.size(); i++) {
        if (s[i] == '.')
            continue;
        t.push_back(s[i]);
        cnt++;
        if(cnt==n)
            break;
    }
    if (cnt < n) {
        t += string(n - cnt, '0');          //如果数字不够,补'0'
    }
    return t;
}

输入和输出

void solve() {                                                              //@处理总输入输出的问题
    cin >> N >> s1 >> s2;
    int s1_n = get_len(s1);
    int s2_n = get_len(s2);
    string ss1 = move(get_str(s1));
    string ss2 = move(get_str(s2));
    if (ss1 == ss2) {
        printf("YES 0.%s*10^%d", ss1.c_str(), s1_n);
    } else {
        printf("NO 0.%s*10^%d 0.%s*10^%d", ss1.c_str(), s1_n, ss2.c_str(), s2_n);
    }
}

整合代码提交

效率勉强还行🐱‍🏍

#include <bits/stdc++.h>
using namespace std;
string s1, s2;
int N;
int get_len(string& s) {                                                    //@用于处理指数的大小
    int pos = s.find('.');
    int start = 0;
    while (start < s.size() && (s[start] == '0' || s[start] == '.'))start++;
    if (pos == string::npos)pos = s.size();
    if (start == s.size())return 0;         //全是0的情况
    if (pos > start)return pos - start;     //小数点在第一位有效数字后面
    return pos - start + 1;                 //小数点在第一位有效数字前面
}
string get_str(string& s) {                                                 //@返回答案字符串
    string t = "";
    int n = N;
    int cnt = 0;
    int start = 0;
    while (start < s.size() && (s[start] == '0' || s[start] == '.'))start++;//处理前导0
    for (int i = start; i < s.size(); i++) {
        if (s[i] == '.')
            continue;
        t.push_back(s[i]);
        cnt++;
        if(cnt==n)
            break;
    }
    if (cnt < n) {
        t += string(n - cnt, '0');          //如果数字不够,补'0'
    }
    return t;
}
void solve() {                                                              //@处理总输入输出的问题
    cin >> N >> s1 >> s2;
    int s1_n = get_len(s1);
    int s2_n = get_len(s2);
    string ss1 = move(get_str(s1));
    string ss2 = move(get_str(s2));
    if (ss1 == ss2) {
        printf("YES 0.%s*10^%d", ss1.c_str(), s1_n);
    } else {
        printf("NO 0.%s*10^%d 0.%s*10^%d", ss1.c_str(), s1_n, ss2.c_str(), s2_n);
    }
}
int main() {
    solve();
    return 0;
}
发表于 2021-10-03 18:27:21 回复(0)
#include <iostream>
#include <math.h>
#include <string>
using namespace std;
string transform(int n, string x) {
	for (int i = 0; i < x.size(); i++) {
		if (x[i] != '0' || (x[i] == '0'&&x[i + 1] == '.'))break;
		if (x[i] == '0') {
			x.erase(i, 1);
			i = -1;
		}
	}
	int pos = x.find('.');
	if (pos != x.npos) x.erase(pos, 1);
	else pos = x.size();
	string sub;
	if (x[0] == '0') {
		for (int i = 1; x[i] == '0'; i++)pos++;
		if (x.size() == pos) {
			pos = 0;
			sub = string(n, '0');
		}
		else {
			int len = x.size() - pos;
			if (len < n) {
				sub = x.substr(pos, len) + string(n - len, '0');
			}
			else sub = x.substr(pos, n);
			pos--;
		}
		pos = -pos;
	}
	else {
		int len = x.size();
		if (len < n) {
			sub = x + string(n - len, '0');
		}
		else sub = x.substr(0, n);
	}
	sub = "0." + sub + "*10^" + to_string(pos);
	return sub;
}
int main() {
	ios::sync_with_stdio(false);
	int n;
	string x, y;
	while (cin >> n >> x >> y) {
		if (n == 0)return 0;
		string new_x = transform(n, x);
		string new_y = transform(n, y);
		if (new_x == new_y) {
			cout << "YES" << ' ' << new_x << endl;
		}
		else {
			cout << "NO" << ' ' << new_x << ' ' << new_y << endl;
		}
	}
}
注意输入的格式存在  00000001 ,并不是真正意义上的数字!!

发表于 2021-03-10 15:45:03 回复(0)
#include<iostream>
#include<string>
using namespace std;

int N;
string s1, s2;
string format(string s,int* p) {
	string ns;
	int loc, nzero, i, j;
	//------------------预处理,获取小数点位置,第一个非零位置,去除前面多余0-------------------------
	for (loc = 0; loc < s.size() && s[loc] != '.'; loc++);//小数点位置
	for (nzero = 0; nzero < s.size() && (s[nzero] == '0' || s[nzero] == '.'); nzero++);//第一个非零位置
	if (nzero > 0&& nzero < loc)//去除多余0
	{
		s = s.substr(nzero, s.size() - nzero);
		loc -= nzero;
		nzero = 0;
	}
	//-------------------下面获取新字符串ns-------------------------------------------------------------------
	//从第一个非零位置开始截取N长度(可能含有小数点要去掉)
	for (i=nzero; i < s.size()&&ns.size()<N; i++) 
		if (i != loc)ns += s[i];
	if (ns.size() < N)	//长度不够补0
		for (i = ns.size(); i < N; i++) ns += "0";
	//-------------------下面处理指数p-------------------------------------------------------------------------
	//第一种,非零在小数点左边,说明大于等于1,幂直接取小数点位置(可能整数,loc直接末尾)
	if (nzero < loc)*p = loc;	
	//第二种,全零情况(此时nzero在末尾)
	else if (nzero == s.size())*p = 0; 
	//第三种,非零在小数点右边,说明小于1,幂取小数点位置-非零位置+1
	else *p = loc - nzero + 1;
	return ns;
}
int main() {
	cin >> N >> s1 >> s2;
	string ns1, ns2;
	int p1, p2;
	ns1 = format(s1, &p1);
	ns2 = format(s2, &p2);
	if (ns1 == ns2 && p1 == p2)
		cout << "YES" << " 0." << ns1 << "*10^" << p1;
	else
		cout << "NO"<< " 0." << ns1 << "*10^" << p1<< " 0." << ns2 << "*10^" << p2;
	return 0;
}


编辑于 2021-02-24 13:19:51 回复(0)
记录一下算法笔记中提供的思路
#include <iostream>
#include <string>
using namespace std;
int e,n;
//①先去掉开头的0(无用),然后去找小数点的位置
//②如果紧接的就是小数点,则需要考虑小数点后面的0需要去掉,同时对指数进行--
//③如果不是,则需要往后面找小数点,找的过程中给指数++,找到后将其去掉
//④比较两者是同时看经过上述处理后的n位字符串与指数的大小

//巧妙的是用string来做
string str(string s){
    e=0;
    string res="";
    while(s.length()>0&&s[0]=='0'){//①
        s.erase(s.begin());
}

    if(s[0]=='.'){//②
        s.erase(s.begin());
        while(s.length()>0&&s[0]=='0'){
            s.erase(s.begin());
            e--;
        }
    }else{//③
        int i=0;
        while(i<s.length()&&s[i]!='.'){
            i++;
            e++;
        }
        if(i<s.length()) s.erase(s.begin()+i);
    }
    if(s.length()==0) {e=0;}
    //④
    int j=0,num=0;
    while(num<n){
        if(num<s.length())res+=s[j++];
        else res+='0';
        num++;
    }
    return res;
}
int main()
{
    //YES 0.123*10^5
    for(int i=0;i<12;i++){
    string s1,s2;
    int e1,e2;
    cin>>n>>s1>>s2;
    s1=str(s1);
    e1=e;
    s2=str(s2);//进行处理,返回处理后的字符串
    e2=e;
    if(s1==s2&&e1==e2) cout<<"YES 0."<<s1<<"*"<<"10^"<<e1<<endl;
    else cout <<"NO 0."<<s1<<"*"<<"10^"<<e1<<" 0."<<s2<<"*"<<"10^"<<e2<<endl;
    }
    return 0;
}

编辑于 2020-08-06 18:08:14 回复(0)
      这题真的。。。。我觉得是个人都不想做,做了我大半天。记录一下
首先,这是肯定不能用doule来存的,因为毕竟精度太高了,题目说了两个数的小数位和小于100位,有效位数小于100位,肯定远超double64位二进制。
     用字符串存了后,分第一位是不是’0‘来处理,
     若第一位不是’0‘,则说明是类似于12358或者12358.9这类的数,这样找到小数点的位置就可以知道其指数的大小,并将小数点从字符串中去掉,如果没有小数点则说明是整数,这样整个字符串的大小就是指数。同时根据有效位数和字符串大小将最终要得的尾数算出来(这里的尾数是指0.%d这里的数),注意如果原字符串的大小小于N,则在后面不错N-size个’0‘。否则从N处截断原字符串作为结果。
     若第一位是0,这里情况就多了,测试数据我真的不想吐槽,我猜测有0,0.00还有0000000之类的。
如果对于这三种的的话很简单就是N个’0‘,同时指数也为0。这里我不太清楚为啥指数一定是0,我猜测是保持一致性,(0.1,10)指数都是0。然后对于0.000012344这类数,找出小数点位置i和第一位不为0的数的位置j,那么指数就是j-i,然后从第一位不为0的数开始截取N个或者达到字符串的尾部。最后再考虑要不要添0。
对于输出格式,我也想吐槽,按照道理来讲,如果指数为0或1的时候,不应该显示出来。比如10^0应该不用写出来,10^1直接写成10,但是题目是要求全部打出来,可能是题目没说清楚或者我自作多情了Hhhh...

#include<iostream>
(720)#include<vector>
#include<algorithm>
(831)#include<cmath>
#include<string>
using namespace std;
int n;
vector<string>vecnumber;
vector<int>vecindex;
void changeV(string a) {
	int num = 0, i = 0;
	string result="";
	if (a[0] != '0') {
		while(a[i]!='.'&&i<a.size()){//12358   123.94
			i++;
		}
		if (i != a.size()) {
			a.erase(i,1);
		}
		int j = 0;
		for (; j < a.size()&&j<n; j++) {
			result+=a[j];
		}
		while (j < n) {
			result += '0';
			j++;
		}
		vecnumber.push_back(result);
		vecindex.push_back(i);
		return;
	}
	else {//0.00159  0.00  0
		if (a.size() == 1) {// 0的情况
			int num = 0;
			while (num<n) {
				result += '0';
				num++;
			}
			vecnumber.push_back(result);
			vecindex.push_back(0);
			return;
		}
		while (a[i] != '.'&&i<a.size()) {
			i++;
		}
		if (i != a.size()) {
			a.erase(i, 1);
		}
		int j = 0;
		while (a[j] == '0' && j < a.size()) {
			j++;//第一位不是0的数
		}
		if (j == a.size()) {//0.00的情况   0.000*10^0
			int num = 0;
			while (num < n) {
				result += '0';
				num++;
			}
			vecnumber.push_back(result);
			vecindex.push_back(0);
			return ;//
		}
		int k = 0;
		int tmp = -1 * (j - i);
		for (; j < a.size() && k < n; j++) {
			result+= a[j];
			k++;
		}
		while (k < n) {
			result += '0';
			k++;
		}
		vecnumber.push_back(result);
		vecindex.push_back(tmp);
		return ;
	}
}
int main() {
	string a, b;
	cin >> n >> a >> b;
	changeV(a);
	changeV(b);
	if (vecnumber[0] == vecnumber[1] && vecindex[0] == vecindex[1]) {
		printf("YES 0.");
		cout << vecnumber[0];
			printf("*10");
				printf("^%d", vecindex[0]);
		return 0;
	}
	printf("NO 0.");
	cout << vecnumber[0];
		printf("*10");
			printf("^%d", vecindex[0]);
	//第二数
	printf(" 0.");
	cout << vecnumber[1];
		printf("*10");
			printf("^%d", vecindex[1]);
}


发表于 2020-02-29 17:54:24 回复(0)
#include<iostream>
#include<string>
using namespace std;

void format(string &str,int n,int &k) {
	while (str[0] == '0') str.erase(0, 1);
	int dot = str.find_first_of('.');
	if (dot == -1) k = str.length();
	else { 
		k = dot;
		str.erase(dot, 1);
		while (str[0] == '0') {
			str.erase(0, 1);
			k--;
		}
		if (str == "") k = 0;
	}
	if (str.length() >= n) str = str.substr(0, n);
	else while (str.length() != n) str += '0';
}

int main() {
	int n,len1,len2;
	string str1, str2;
	cin >> n >> str1 >> str2;
	format(str1, n,len1);
	format(str2, n, len2);
	if (str1 == str2 && len1 == len2) cout << "YES 0." << str1 << "*10^" << len1;
	else cout << "NO 0." << str1 << "*10^" << len1 << " 0." << str2 << "*10^" << len2;
	return 0;
}

发表于 2020-02-08 15:26:48 回复(0)
三个注意点:前导0和数值上为0,以及小数点
#include<iostream>
#include<string>
using namespace std;

typedef pair<string,int> psi;
string s1,s2;
int len;
//1.001
psi standardlize(string str) {
	int delzeros = 0;
	while(str[delzeros] == '0')
		str = str.substr(1,str.length()); // 删除前导零
	string ans = "0."; // 构造答案字符串
	int strlen = str.length();
	int poipos = strlen;
	for(int i = 0; i < strlen; ++i) {
		if(str[i] == '.') {
                    poipos = i;
                    break;
                } //找出小数点位置
	}

	int first = 0;
	while(first < strlen && (str[first] == '0' || str[first] == '.')) {
		++first; // 找出第一个有效数字
	}
	for(int i = first; i < first+len; ++i) { // 取len位有效数字
		if(i < strlen) {
			if(str[i] == '.') { // 碰到小数点跳过,同时补偿一下消耗的一位
				continue;
				++len; // len后面用不着了,自增一次补偿小数点的占位
			}
			ans += str[i];
		} else ans += '0'; // 给的数字不够用了就要自己补0
	}
	ans += "*10^";
	int exponent;

	if(first == strlen) { // 数值上为0,比较特殊,所以特殊处理
		exponent = 0;
	} else {
		if(first > poipos) { // 指数部分取多少位,画图画画就能看出关系来
			exponent = -(first - poipos-1);
		} else {
			exponent = poipos;
		}
	}
	return make_pair(ans,exponent); // 用pair返回俩值,省了判断正负号再贴到尾巴上的麻烦
}

//
int main() {
	cin >> len >> s1 >> s2;
	psi ans1 = standardlize(s1);
	psi ans2 = standardlize(s2);

	if(ans1 == ans2) {
		cout << "YES" << " " << ans1.first << ans1.second;
	} else {
		cout << "NO" << " " << ans1.first << ans1.second << " " << ans2.first << ans2.second;
	}
	return 0;
}


发表于 2020-01-23 21:03:35 回复(0)