科学计数法

任给一个十进制正数 M>0 (M 可能为整数或小数,且最多包含 200 位数字)。写一个程序将其转换成科学计数法表示,形式为 aFb。其中 1≤a<10 且不含前置 0,a 的长度为给定精度 p (p 包括 a 中整数及小数部分但不包含小数点)。a 的值由四舍五入方法确定,M 中有效数字长度小于 p 时,后面填充 0 补足。b 为指数,b=0 时,省略指数部分。

输入格式
第 1 行:一个整数 T(1≤T≤10)为问题数。

每组测试数据为一行,包含两个数字,之间由一个空格分开。第一个数字是待转换数字 M,第二个数字是要求的输出精度 p (1<p≤30)。

输出格式
对于每个问题,输出一行问题的编号(0 开始编号,格式:case #0: 等)。

然后接下来一行中输出给定数字的科学计数法表示。

样例

input
3
123456789 8
0.0045678 3
1.8 4

output
case #0:
1.2345679F8
case #1:
4.57F-3
case #2:
1.800

思路:
这是一道踩了坑的题。首先就是进位问题。我的思路是先算出aFb中的b部分,再提取数字出来处理进位。
但忘记了如果是99999999的情况,进位会导致溢出,以及串长度小于p的情况。
所以码完题之后又借鉴了一下dalao们的做法。

代码
相当粗鄙的解法。

#include <cctype>
#include <iostream>
#include <string>
using namespace std;
int p, t, b;
string m;

int main() {
    cin >> t;
    for (int k = 0; k < t; k++) {
        cin >> m >> p;
        while (m.front() == '0')
            m.erase(m.begin());
        if (m.front() == '.') {
            for (int i = 1; i < m.length(); i++) {
                if (m[i] > '0') {
                    b = -i;
                    break;
                }
            }
        } else
            b = (m.find('.') == m.npos ? m.length() : m.find('.')) - 1;
        string copy{};
        for (auto i : m) {
            if (isdigit(i))
                copy += i;
        }
        while (copy.front() == '0')
            copy.erase(copy.begin());
        if (copy.length() > p) {
            if (copy[p] >= '5')
                copy[p - 1]++;
            for (int i = p - 1; i >= 1; i--) {
                copy[i - 1] += copy[i] / ('9' + 1);
                copy[i] %= '9' + 1;
                if (copy[i] < '0')
                    copy[i] += '0';
            }
            if (copy[0] == '9' + 1) {
                copy[0] %= ('9' + 1);
                if (copy[0] < '0')
                    copy[0] += '0';
                copy.insert(copy.begin(), '1');
                b++;
            }
        } else {
            for (int i = copy.length() - 1; i < p; i++)
                copy += '0';
        }
        cout << "case #" << k << ":\n" << copy[0] << ".";
        for (int i = 1; i < p; i++)
            cout << copy[i];
        if (b)
            cout << "F" << b;
        cout << endl;
    }
    return 0;
}

2
dalao的优美代码。

#include<bits/stdc++.h>
using namespace std;
auto const P(30);
int main()
{
    int T; cin >> T;
    for(int cs = 0; cs < T; cs++)
    {
        cout << "case #" << cs << ":\n";
        string m; int p; cin >> m >> p; m +='0'; // 开头补个0防溢出
        int b = 0;
        if(auto dot = m.find('.'); dot != m.npos)
        {
            b = dot - m.length() + 1;
            m.erase(dot, 1);
        }
        auto nz = m.find_first_not_of('0'); // nz: not_zero
        b += m.length() - nz - 1;
        m += string(P, '0'); // 不管精度够不够,末尾先补它30个0
        m[nz + p - 1] += m[nz + p] >= '5';
        for(int i = nz + p - 1; m[i] > '9'; i--)
        {
            m[i] -= 10; m[i - 1] += 1;
        }
        if(m[nz - 1] - '0') // 把类似10.0F1的情况改成1.0F2
        {
            nz -= 1; b += 1;
        }
        cout << m[nz] << ".";
        for(size_t i = nz + 1; i < nz + p; i++)cout << m[i];
        if(b)cout << "F" << b;
        cout << "\n";
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值