You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++自定义字符串转数值函数结果自动舍入问题求助

字符串转数值时的舍入问题分析

问题概述

编写了一个C++程序实现字符串转数值,先后使用double和float类型,处理带小数的输入(如1234.6789)时,结果总会自动舍入最后一位,添加调试输出仍未定位原因,需技术分析。

程序代码

#include <iostream>
using namespace std;

//variables initialised in a set of curly brackets are called local variables
//variables initialised outside a set of curly brackets are called global variables
// local variables can only be used in that set of curly brackets
// global variables can be used anywhere after it has been declared
// global variables are automatically set to 0 when it has not been assigned a value
//a void function is a function that returns nothing

//StringName.length() returns the length of a string


/*----------------------------------------FUNCTION-------------------------------------*/
int pow(int a, int b){
int c = 1;
for(int i=0;i<b;i++){
    c*=a;
}
return c;
}

float StringNoToNo(string a){
float b=0.0;
int y = 1;
int s = 0;
//cout<<"a.length() is: "<<a.length()<<endl;
for(int i = (a.length()); i>0;i--){
  //  cout<<"the loop: "<<(a.length()-i)<<endl;
    int z = a[i-1];
    //cout<<"z = "<<z<<endl;
    switch(z){
     case 48 ... 57:
      //    cout<<"(a[i]>=48)&&(a[i]<=57) is true"<<endl;
//cout<<"pow(10.0,(a.length()-i)) = "<<pow(10.0,(a.length()-i))<<endl;
//cout<<"a.length() - i = "<<(a.length()- i)<<endl;
    b += ((a[i-1]-48)* pow(10.0,(a.length()-i-s)));
  //  cout<<"b= "<<b<<endl;
    break;
     case 46:
        y=pow(10,(a.length()-i));
    //    cout<<"y = "<<y<<endl;
        if(s==0){
        s++;}else{
        goto v;
        }
        break;
    default:
        v:
      //  cout<<"(a[i]<48)||(a[i]>57) is true"<<endl;
        cout<< "the number was not written properly"<<endl;
        return 0;
        break;
    }
}
//cout<<" b = "<<b<<endl;
//cout<<"b/y = "<<b/y<<endl;
return (b/y);
}
/*----------------------------------------FUNCTION-------------------------------------*/
// overloading functions - you can create multiple functions with the same name so as long
// as they have different parameters.
// as long as the function is declared at the beginning, even if the function meant to
// overload it is written at the end of the code, it can still be used.

main() {
  string no;
  cout << "write a number: ";
  cin >> no;
  cout << "the number is: "<<StringNoToNo(no)<<endl;
}

输入输出示例

write a number: 1234.6789
the number is: 1234.68

Process returned 0 (0x0)   execution time : 4.713 s
Press any key to continue.

调试输出

write a number: 1234.6789
the number is: a.length() is: 9
the loop: 0
z = 57
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 1
a.length() - i = 0
b= 9
the loop: 1
z = 56
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 10
a.length() - i = 1
b= 89
the loop: 2
z = 55
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 100
a.length() - i = 2
b= 789
the loop: 3
z = 54
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 1000
a.length() - i = 3
b= 6789
the loop: 4
z = 46
the loop: 5
z = 52
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 100000
a.length() - i = 5
b= 46789
the loop: 6
z = 51
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 1000000
a.length() - i = 6
b= 346789
the loop: 7
z = 50
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 10000000
a.length() - i = 7
b= 2.34679e+06
the loop: 8
z = 49
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 100000000
a.length() - i = 8
b= 1.23468e+07
1234.68

Process returned 0 (0x0)   execution time : 24.055 s
Press any key to continue.

原因分析

  1. float类型的精度限制
    float仅能提供约6-7位有效数字,输入值1234.6789包含8位有效数字,超出float的精确存储范围。从调试输出可见,当累加至2.34679e+06时,数值已出现舍入,最终结果自然无法保留全部小数位。即使改用double,若输出时未指定精度,默认输出也可能因格式问题显示舍入后的结果。

  2. 自定义pow函数的隐患
    自定义的pow函数返回int类型,当计算高次幂时可能触发整数溢出(例如pow(10, 10)会超出32位int的最大值),且调用时传入10.0会被隐式转换为int类型,虽未在当前案例中直接引发问题,但会导致浮点运算精度损失。

  3. 输出格式的默认行为
    cout输出浮点值时,默认仅显示6位有效数字,因此1234.6789会被格式化为1234.68(四舍五入到6位有效数字)。

解决建议

  1. 改用double类型存储
    将StringNoToNo函数的返回值和变量b改为double,double支持15-17位有效数字,足以精确存储当前输入的数值。

  2. 替换自定义pow为标准库函数
    移除自定义的pow函数,包含<cmath>头文件后使用标准库的std::pow函数,或改用逐步累加的方式构建数值(例如:b = b * 10 + (a[i-1]-48)),避免整数溢出和精度损失。

  3. 控制输出精度
    在输出结果前添加格式控制,例如:

    cout << fixed << setprecision(4) << "the number is: "<<StringNoToNo(no)<<endl;
    

    需包含<iomanip>头文件,确保输出保留指定的小数位数。

内容的提问来源于stack exchange,提问作者Shuayeb Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 15:25:15