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.
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; }
//原来小数点和第一个有效数字位的位置才是这道题的关键,而不是分析各种可能情况的细节! #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; } } }
//关键:把浮点数按字符串考虑,标记小数点位置与首个非零位 #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; }
#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
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])
#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; }
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; } }
#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'; } } }
更多PAT甲级题解--acking-you.github.io
这道题有有点坑坑的,最开始的前情提要过于的晦涩,开始无故就说一个机器只能保存三个有效数字,结果没给出丝毫有用的信息总结!
我后面翻了下别人的题解,发现原来是这个题意:
给出两个数,问将它们写成保留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; //小数点在第一位有效数字前面 }
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; }
#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 ,并不是真正意义上的数字!!
#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; }
#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; }
#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]); }
#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; }
#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; }