大数计算思路

一、本题核心大数思路(题目: d×2nd \times 2^n 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,不用移动数组,大模拟首选!

  1. 每一轮:所有位 ×2
css 复制代码
for(int i = 0; i < d.size();i++) d[i]*=2;
  1. 统一处理进位:从低位(i=0)到高位
ini 复制代码
for(int i = 1;i< d.size();i++){
    d[i]+= d[i-1]/10; //低位的进位加到高位
    d[i-1]%= 10;      //低位保留个位
}
  1. 最高位单独判断进位:如果最高位≥10,保留个位,数组后面新增一位1
scss 复制代码
if(d.back()>=10){
    d.back()%=10;
    d.push_back(1);
}

注意:这是反复乘2,不是大数×大数;是高精度数乘以小整数(2),难度更低,CSP高频。

  1. 乘完n次之后,四舍五入:看point这一位,如果>=5,point+1的位置+1,再处理进位。
  2. 最后输出:从最高位输出到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);        //删掉小数点
  1. string::find string.find(字符):查找字符第一次出现的下标,下标从0开始。
  • 找到:返回下标;找不到返回 string::npos

  • 这里point = s.find('.'),获取小数点在反转后的字符串里面的位置。

    例:反转后s="41.3",find('.')返回2。

  1. 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(),动态跟随数组长度变化。

四、整体流程极简梳理

  1. 读入n和小数字符串s;
  2. reverse反转字符串,低位放前面,适配逆序大数数组;
  3. find找到小数点位置,erase删除小数点;
  4. 字符转数字,存入vector(逆序存储);
  5. 循环n次,大数整体 ×2,处理进位;
  6. 判断point位置,完成四舍五入、进位传递;
  7. 从高位向低位输出结果。

五、考点总结(CSP大模拟)

  1. 高精度乘小整数:逆序存储数字是标准套路,方便进位;

  2. string处理:find定位符号、erase删除字符,搭配reverse处理小数;

  3. 坑点提醒:

    • 进位循环起点,不要漏掉最低位的进位;
    • 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;
}
相关推荐
高晶1 小时前
主从自动分配算法:平均值乘以设备数一半的选举基准值解析
算法·设计模式·程序员
学电子她就能回来吗1 小时前
LeetCode Hot 100|普通数组专题学习笔记(零基础版)
笔记·算法·leetcode
用户老李1 小时前
反向传播计算梯度举例
算法
niyongsheng1 小时前
多智能体连续时间内路径规划:AA-SIPP(m) 的 Rust 实现与算法
算法·rust·机器人
302wanger2 小时前
DeepSeek-V4.1-Flash-1017 免费用到1024,速来
算法
lisw053 小时前
微分与积分的本质区别解析
算法·数学建模·极限编程
xys_6783 小时前
深挖数据结构:树和二叉树(上)
数据结构·算法
Interview Aid1124 小时前
Google SWE Intern VO 面经:两轮 Coding,Follow-up 考察 BFS 状态
算法
琳达爱分享4 小时前
从单机令牌桶到集群限流:一次配额超发的复盘
后端·算法