PAT 乙级 1024 科学计数法
- 1. 题目简述及在线测试位置
- 2. 基本思路
- 3. 完整AC代码
1. 题目简述及在线测试位置
1.1 输入是科学计数法格式 ,输出是普通数字表示法格式,要求所有有效位都被保留,包括末尾的0
1.2 在线测试位置:PAT 1024 科学计数法
2. 基本思路
2.1 科学计数法就是将一个数表示成 a与10的n次幂相乘的形式。比如 +1.23400E-03,就是 +1.23400 与 10的-3次方 相乘,E表示10的次方
2.2 通过字符串存储输入的数字,然后以 E 为分隔点,将字符串分割为两部分 E前的字符 1.23400、E后的字符 -03 (对于 首位符号位 不存储,判定后直接打印输出)
2.3 E后的字符用于计算10的次方数
for (int k = afterCount - 1; k >0; k--) // +1.23400E-03 , 将E后 不包含符号的字符(符号位是k=0) 转换为数字,这个数字就是10的次方数
{
Base += (After[k] - '0') * Scale; //若Base=3,代表有3个0
Scale *= 10;
}
2.4 E前的字符按格式打印输出,本题的难点是 什么时候打印小数点。这里分两个情况:E后的符号为负 -,表示10的负x次方 ; 符号为正,表示10的正x次方。符号为负-时,打印 E前的字符 前,先输出0和小数点:有几次方,就输出几个0,小数点处于第一个0的后面
if (After[0] == '-') //+1.23400E-03 处理E后为-的情况
{
cout << "0"; Base--;
cout << ".";
while (Base != 0)
{
cout << "0";
Base--;
}
for (j=0; j < beforeCount; j++)
if (Before[j] != '.')
cout << Before[j];
}
2.5 符号为正+时,先打印 E前的字符 ,对于小数点之后的数字,边打印、边统计消耗的次方数(即:小数点的移动位置)。这里可以设定一个循环,直到E前的字符打印完再退出,同时判定 次方数的消耗情况。当此循环退出时,可能有三个情况:情况一,循环正常退出,10的次方数中的次方数没打印完,需要补0,此时不用打印小数点 ; 情况二, 循环异常退出(因为10的次方数消耗完了),此时打印小数点 及 其余未打印的字符;情况三,次方数和Before数组都打印完了,此时不需要动作
else if (After[0] == '+') //-1.2E+10 处理E后为+的情况
{
cout<<Before[0];
//Before[1]是小数点,先跳过,后面视情况决定什么时候打印
j=2;
while (j<beforeCount) //E前的字符打印完再退出
{
cout << Before[j++];
Base--;//对于小数点之后的数字,边打印、边统计小数点的移动位置
if (Base == 0)
break;
}
if (Base > 0) //10的次方数中的次方数没打印完
{
while (Base != 0)
{
cout << "0";
Base--;
}
}
else if (Base == 0 && j<beforeCount) //次方数打印完了,但是Before数组没打印完,需要加小数点 .
{
cout << ".";
while (j < beforeCount)
cout << Before[j++];
}
//else //次方数和Before数组都打印完了
3. 完整AC代码
#include <iostream>
using namespace std;
#define MAX 10000
int main()
{
string number; // number +1.23400E-03
int i=0; //跟踪number数组的位置
char Before[MAX]; //数组Before用于存储E之前的字符(不包含最前的数值符号)
char After[MAX]; //数组After用于存储E之后的字符(不包含E)
int beforeCount = 0,afterCount=0; //Before After数组的计数器
int j = 0;//跟踪Before After数组的位置
int Base=0,Scale=1; //10的次方数, 计量单位
cin >> number;
if (number[i++] == '-') //打印首位符号位
cout << "-";
for (; number[i] != 'E'; i++)// 数组Before用于存储E之前的字符(不包含最前的数值符号)
Before[beforeCount++]=number[i];
i++; //跳过字符E
for (; i < number.length(); i++) //数组After用于存储E之后的字符(不包含E)
After[afterCount++]=number[i];
for (int k = afterCount - 1; k >0; k--) // +1.23400E-03 , 将E后 不包含符号的字符 转换为数字
{
Base += (After[k] - '0') * Scale;
Scale *= 10;
}
if (After[0] == '-') //+1.23400E-03 处理E后为-的情况
{
cout << "0"; Base--;
cout << ".";
while (Base != 0)
{
cout << "0";
Base--;
}
for (; j < beforeCount; j++) //j初始值为0
if (Before[j] != '.')
cout << Before[j];
}
else if (After[0] == '+') //-1.2E+10 处理E后为+的情况
{
cout << Before[0];
//Before[1]是小数点,先跳过,后面视情况决定什么时候打印
j = 2;
while (j < beforeCount) //E前的字符打印完再退出
{
cout << Before[j++];
Base--;//对于小数点之后的数字,边打印、边统计小数点的移动位置
if (Base == 0) //次方数打印完就退出
break;
}
if (Base > 0) //10的次方数中的次方数没打印完
{
while (Base != 0)
{
cout << "0";
Base--;
}
}
else if (Base == 0 && j < beforeCount) //次方数打印完了,但是Before数组没打印完,需要加小数点 .
{
cout << ".";
while (j < beforeCount)
{
cout << Before[j++];
}
}
//else //次方数和Before数组都打印完了
}
return 0;
}