题目描述
小蓝最近在研究一种浮点数的表示方法:R 格式。对于一个大于 0 的浮点数 d,可以用 R 格式的整数来表示。给定一个转换参数 n,将浮点数转换为 R 格式整数的做法是:
-
将浮点数乘以 2n。
-
四舍五入到最接近的整数。
输入格式
一行一个整数 n 和一个浮点数 d。
输出格式
一行一个整数表示 d 用 R 格式表示出的值。
输入输出样例
输入 #1复制
2 3.14
输出 #1复制
13
说明/提示
样例 1 解释
3.14×22=12.56,四舍五入后为 13。
数据规模与约定
用 t 表示将 d 视为字符串时的长度。
-
对于 50% 的数据,保证 n≤10,t≤15。
-
对于全部的测试数据,保证 1≤n≤1000,1≤t≤1024,保证 d 是小数,即包含小数点
暴力解法(通过50%)
#include<bits/stdc++.h>
using namespace std;
int n;
double d;
int main()
{
cin>>n>>d;
double ans=d*pow(2,n);
long long res=round(ans);
cout<<res<<endl;
return 0;
}
计算平方的函数pow(2,n)
四舍五入函数round(ans);
AC解法(通过100%)
#include <bits/stdc++.h>
using namespace std;
const int N=1000005;
int n;
int a[N];
int len;
int mt;
int main() {
scanf("%d",&n);
string d;
cin>>d;
bool flag=false;
for (int i=d.size()-1;~i;--i) {
if (d[i]=='.') {
flag=true;
continue;
}
a[++len]=d[i]-'0';
if (!flag) mt++;
}
for (int i=1;i<=n;++i) {
int j=1,jw=0;
while (j<=len || jw) {
a[j]<<=1;
a[j]+=jw;
jw=a[j]/10;
a[j]%=10;
++j;
}
--j;
len=j;
}
if (a[mt]>=5) {
int i=mt+1;
a[i]++;
while (a[i]>=10) {
a[i+1]+=a[i]/10;
a[i]%=10;
++i;
}
}
int t=N-1;
while (t>=mt+1 && !a[t]) t--;
if (t<mt+1) puts("0");
else {
for (int i=t;i>=mt+1;--i) {
printf("%d",a[i]);
}
}
return 0;
}
下面有详细解释注释:
#include <bits/stdc++.h>
using namespace std;
// 定义数组的最大长度
const int N = 1000005;
// n 表示要将输入的小数乘以 2 的 n 次幂
int n;
// 用于存储小数的每一位数字,整数部分和小数部分一起存储
int a[N];
// len 记录存储在数组 a 中的数字的长度
int len;
// mt 记录小数点的位置
int mt;
int main() {
// 读取输入的整数 n
scanf("%d", &n);
// 用于存储输入的小数
string d;
cin >> d;
// 标记是否遇到小数点
bool flag = false;
// 从输入小数的末尾开始向前遍历
for (int i = d.size() - 1; ~i; --i) {
// 如果当前字符是小数点
if (d[i] == '.') {
// 标记遇到了小数点
flag = true;
continue;
}
// 将字符转换为数字并存储到数组 a 中,同时长度加 1
a[++len] = d[i] - '0';
// 如果还没遇到小数点,说明是整数部分,mt 加 1
if (!flag) mt++;
}
// 进行 n 次乘以 2 的操作
for (int i = 1; i <= n; ++i) {
int j = 1, jw = 0;
// 模拟乘法运算,处理每一位数字
while (j <= len || jw) {
// 当前位数字乘以 2
a[j] <<= 1;
// 加上进位
a[j] += jw;
// 计算新的进位
jw = a[j] / 10;
// 当前位数字取模 10
a[j] %= 10;
// 处理下一位
++j;
}
// 调整数组长度
--j;
len = j;
}
// 判断小数部分的第一位是否大于等于 5,进行四舍五入
if (a[mt] >= 5) {
int i = mt + 1;
// 小数部分进位
a[i]++;
// 处理进位
while (a[i] >= 10) {
a[i + 1] += a[i] / 10;
a[i] %= 10;
++i;
}
}
// 去除整数部分末尾的 0
int t = N - 1;
while (t >= mt + 1 && !a[t]) t--;
// 如果整数部分没有非零数字,输出 0
if (t < mt + 1) puts("0");
else {
// 输出整数部分
for (int i = t; i >= mt + 1; --i) {
printf("%d", a[i]);
}
}
return 0;
}