一、本题核心大数思路(题目: d×2n,最后在point位置四舍五入)
原理:先把小数反转、去掉小数点,模拟高精度 ×2 共n次,最后按小数点位置做四舍五入。 样例:输入
2 3.14原始:3.14 → 反转字符串变成41.3,找到小数点位置point=2,erase删掉.,字符串变成413,数组d=4,1,3。 point-- 后point=1,这个point记录原来小数点的位置。 循环n次:数组整体 ×2,处理进位(这就是大数乘2)。
✅ 大数乘2核心思路(你的代码版本,数组存逆序数字,重点!)
【关键约定】数组d是逆序存储 :d0 是个位,d1十位,d2百位...... 例:数字314,数组存成
d[0]=4, d[1]=1, d[2]=3。 好处:进位只需要往数组下标更大的方向走,新的高位直接push_back,不用移动数组,大模拟首选!
- 每一轮:所有位 ×2
css
for(int i = 0; i < d.size();i++) d[i]*=2;
- 统一处理进位:从低位(i=0)到高位
ini
for(int i = 1;i< d.size();i++){
d[i]+= d[i-1]/10; //低位的进位加到高位
d[i-1]%= 10; //低位保留个位
}
- 最高位单独判断进位:如果最高位≥10,保留个位,数组后面新增一位1
scss
if(d.back()>=10){
d.back()%=10;
d.push_back(1);
}
注意:这是反复乘2,不是大数×大数;是高精度数乘以小整数(2),难度更低,CSP高频。
- 乘完n次之后,四舍五入:看point这一位,如果>=5,point+1的位置+1,再处理进位。
- 最后输出:从最高位输出到point+1的位置。
⚠️ 你代码的一处小bug:进位循环起点写
i=1是错的! 正确写法进位循环应该i从0开始,你现在的代码会漏掉d0产生的进位,这会造成答案错误。
ini//错误(你现在写的) for(int i = 1;i< d.size();i++){ d[i]+= d[i-1]/10; d[i-1]%= 10; } //正确 for(int i = 0;i< d.size();i++){ int carry = d[i]/10; d[i]%=10; if(i+1 < d.size()) d[i+1] += carry; else if(carry>0) d.push_back(carry); }
二、代码里用到 string 函数:find / erase
arduino
ll point = s.find('.'); //找小数点
s.erase(point,1); //删掉小数点
- string::find
string.find(字符):查找字符第一次出现的下标,下标从0开始。
-
找到:返回下标;找不到返回
string::npos -
这里
point = s.find('.'),获取小数点在反转后的字符串里面的位置。例:反转后s="41.3",
find('.')返回2。
- string::erase(pos, length)
s.erase(point,1):从下标point开始,删除1个字符。 这里就是把小数点删掉,只剩下纯数字字符,方便转成大数数组。
三、vector 的 size()
d.size():返回vector容器里面元素的个数 ,返回类型是size_t(无符号整数)。
arduino
vector<ll> d(s.size());
for(int i = 0; i < d.size();i++)
-
d.size() 就是当前这个大数一共有多少位数字。
-
每次push_back之后,size()会自动+1。
注意:循环条件
i < d.size(),动态跟随数组长度变化。
四、整体流程极简梳理
- 读入n和小数字符串s;
- reverse反转字符串,低位放前面,适配逆序大数数组;
- find找到小数点位置,erase删除小数点;
- 字符转数字,存入vector(逆序存储);
- 循环n次,大数整体 ×2,处理进位;
- 判断point位置,完成四舍五入、进位传递;
- 从高位向低位输出结果。
五、考点总结(CSP大模拟)
-
高精度乘小整数:逆序存储数字是标准套路,方便进位;
-
string处理:
find定位符号、erase删除字符,搭配reverse处理小数; -
坑点提醒:
- 进位循环起点,不要漏掉最低位的进位;
find找不到返回string::npos,本题题目保证输入带小数点,所以不用判断;- vector.size()返回无符号数,和int比较一般没问题,但要警惕负数比较。
你想的话,我可以帮你把修正之后完整可AC的代码 写出来,顺便加上注释。 或者,我单独给你整理一份高精度乘小整数的模板,可以直接存到CSP纸质模板里。
c++
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
ll n;
string s;
cin >> n >> s;
reverse(s.begin(),s.end());
ll point = s.find('.');
s.erase(point,1);
point--;
vector<ll> d(s.size());
//转化成数组
for(int i = 0; i < s.size();i++){
d[i] = s[i] - '0';
}
while(n--){
//
for(int i = 0; i < d.size();i++){
d[i]*= 2;
}
for(int i = 1;i< d.size();i++){
d[i]+= d[i-1]/10;
d[i-1]%= 10;
}
if(d[d.size()-1]>=10){
d[d.size()-1] %=10;
d.push_back(1);
}
}
if(d[point] >=5)
{
d[point + 1]++;
}
for(int i = point +2;i<d.size();i++){
d[i]+= d[i-1]/10;
d[i-1]%= 10;
}
if(d[d.size()-1]>=10){
d[d.size()-1] %=10;
d.push_back(1);
}
for(int i = d.size()-1;i > point;i--){
cout << d[i];
}
return 0;
}