W
e
l
c
o
m
e
: )

洛谷UVA 12930 Bigger or Smaller

Description

给定若干对长度 \(\leqslant 100\) 的浮点数 \(a,b\) ,比较两者的大小。

Solution

经过读题可以发现,我们不能使用朴素方法(double)来存储数据。请注意,数字长度可能达到 \(100\) 位。于是,我们想到了一种很简单容易实现的方法:字符串模拟。

由于 C++ 的 string 头文件自带字典序比较,我们可以直接使用字典序模拟数字的比较。

但是,还有一个问题。浮点数可能拥有长度不一的后缀 \(0\) 。例如,\(1.00\)\(1.000\)\(1.0\) 等都是相等的。我们需要设法去除这个后缀。这也是这道题的难点。

首先,我们只需要关注小数部分,即小数点 . 后面的子串。我们遍历小数部分每个数,如果当前位是 \(0\) ,那么我们就进入内层循环。在内层循环里,我们逐个数位往后筛查,直到当前位不是 \(0\) 为止。如果当前内层循环已经到达字符串末尾,则代表后面都是后缀 \(0\) ,可以省略;否则这就是一个普通镶嵌在数字中的 \(0\)

Code

#include <iostream>
#include <string>
using namespace std;

string a, b;
int idx = 1;

string shorten_float_number(string n) {  // 去除后缀0
    int ans = n.size();  // 初始没有后缀
    for (int i = n.find_first_of('.'); i < n.size(); i++) {  // 从小数点一直循环到结束
        if (n[i] == '0') {  // 如果当前位是0,就需要进行判断是否为后缀
            int j = i;  // 从当前位开始循环
            while (n[j++] == '0');  // 看最后哪里不是0
            j--;  // 多加了一个,减掉
            if (j == n.size()) {  // 如果到头了
                ans = i + 1;  // 那么就确定了答案
                break;
            }
        }
    }
    return n.substr(0, ans);  // 返回去除后缀的字符串
}

int main() {
    while (cin >> a >> b) {
        a = shorten_float_number(a), b = shorten_float_number(b);
        string a_integer = a.substr(0, a.find_first_of('.')), b_integer = b.substr(0, b.find_first_of('.'));
        string a_float = a.substr(a.find_first_of('.') + 1, a.size()), b_float = b.substr(b.find_first_of('.') + 1, b.size());
        cout << "Case " << idx << ": ";
        idx++;
        if (a_integer != b_integer) {  // 先判断整数部分
            cout << (a_integer > b_integer ? "Bigger" : "Smaller") << endl;
            continue;
        }
        if (a_float != b_float) {  // 再判断小数部分
            cout << (a_float > b_float ? "Bigger" : "Smaller") << endl;
            continue;
        }
        cout << "Same" << endl;  // 如果都不是,那就是相等
    }
    return 0;
}

蟹蟹阅读!

posted @ 2021-09-08 21:08  samzhangjy  阅读(59)  评论(0)    收藏  举报