当前位置:   article > 正文

C++ 字符串转浮点数,包括整数、小数和科学记数法_c++字符串转浮点数

c++字符串转浮点数

  字符串转浮点数,用stoi(),stod(),stof()等库函数,好像转换精度不够,还特别容易出错。于是就写了一个自定义函数double str2num(string),可以转换包括整数、小数和科学记数法浮点数。代码用了double型变量,整数最长可以保留16位。如果觉得还不够,可以在所有的 double 前添上 long 就能增加到20位精度。还有一点科学记数法只用了e,大写E注意先转小写。小数向0趋近时直接输出0,大于DBL_MAX的输出inf错;输入非数字的情况,人为用pow()函数实现输出nan错。如果取得的数字串已用正则表达式检验过,可以删除掉两个注释符之间的代码。

  1. #include <iostream>
  2. #include <iomanip>
  3. #include <vector>
  4. #include <cmath>
  5. using namespace std;
  6. #define isNum(c) (isdigit(c)?c-48:(c=='e'?10:(c=='.'?11:(c=='-'?12:(c=='+'?13:-1)))))
  7. double str2num(string s)
  8. { //字符串转数字,包括整数、小数和科学记数法
  9. int i,j,k,negative=0;
  10. double n=0;
  11. string s1,s2;
  12. if (s.empty()) return 0;
  13. if (s[0]=='-') negative=1; //设置负数标记
  14. if (s[0]=='+'||s[0]=='-') s=s.substr(1,s.size());
  15. //---------------
  16. for (i=0;i<s.size();i++) //排除不需要的字符
  17. if (isNum(s[i])==-1) return pow(-1.1,1.1);
  18. if (s[0]=='e'||s[0]=='.'||s[s.size()-1]=='e'||s[s.size()-1]=='.')
  19. return pow(-1.1,1.1); //排除 e或. 出现在首尾
  20. i=-1;j=0;
  21. while ((i=s.find('.',++i))!=s.npos) j++;
  22. if (j>1) return pow(-1.1,1.1); //排除多个小数点
  23. i=-1;j=0;
  24. while ((i=s.find('e',++i))!=s.npos) j++;
  25. if (j>1) return pow(-1.1,1.1); //排除多个字母e
  26. if (s.find('e')==s.npos) //没有e时排除加减
  27. if (s.find('+')!=s.npos||s.find('-')!=s.npos) return pow(-1.1,1.1);
  28. //---------------
  29. if ((i=s.find('e'))!=s.npos){
  30. s1=s.substr(0,i); //尾数部分
  31. s2=s.substr(i+1,s.size()); //阶码
  32. if (s2[0]=='+') s2=s2.substr(1,s2.size()); //阶码为正数,去掉+
  33. if (s2.find('.')!=s2.npos) return pow(-1.1,1.1); //阶码不准出现小数
  34. n=str2num(s1)*pow(10.0,str2num(s2)); //尾数和阶码分别递归调用
  35. return negative?-n:n;
  36. }
  37. i=0;k=1;
  38. if ((i=s.find('.'))!=s.npos){
  39. for (j=i+1;j<s.length();j++,k++)
  40. n+=isNum(s[j])/pow(10.0,(double)k);
  41. n+=str2num(s.substr(0,i)); //整数部分递归调用
  42. }
  43. else
  44. for (j=0;j<s.size();j++)
  45. n=n*10+isNum(s[j]);
  46. return negative?-n:n; //负数返回-n
  47. }
  48. int main(void)
  49. {
  50. vector<string>a={"-12","0","+12.345","123456789012345","1.23456789012345e+20",
  51. "-1.5e-2","1e2","3e1.1","1.7977e+308","-4.95e-324","1.1.1","1e2e2","abc","1+2"};
  52. for (auto s:a)
  53. cout<<s<<"->"<<setprecision(15)<<str2num(s)<<endl;
  54. }

测试结果如下:

  1. E:\>test
  2. -12->-12
  3. 0->0
  4. +12.345->12.345
  5. 123456789012345->123456789012345
  6. 1.23456789012345e+20->1.23456789012345e+020
  7. -1.5e-2->-0.015
  8. 1e2->100
  9. 3e1.1->nan
  10. 1.7977e+308->inf
  11. 4.95e-324->0
  12. 1.1.1->nan
  13. 1e2e2->nan
  14. abc->nan
  15. 1+2->nan
  16. E:\>

最后,还是觉得字符串与数字的互转还用<sstream>库函数最方便:

  1. #include <iostream>
  2. #include <iomanip>
  3. #include <sstream>
  4. #include <string>
  5. using namespace std;
  6. string double2str(double d)
  7. {
  8. string s;
  9. stringstream ss;
  10. ss<<setprecision(16)<<d;
  11. s=ss.str();
  12. ss.clear();
  13. return s;
  14. }
  15. double str2double(string s)
  16. {
  17. double d;
  18. stringstream ss;
  19. ss<<s;
  20. ss>>setprecision(16)>>d;
  21. ss.clear();
  22. return d;
  23. }
  24. int main()
  25. {
  26. double x;
  27. string str;
  28. for(;;) {
  29. cin >> str;
  30. x=str2double(str);
  31. cout<<setprecision(16)<<x<<"->|"+double2str(x)+"|"<<endl;
  32. if (x==-1) return 0;
  33. }
  34. }

- 编译器名: TDM-GCC 4.9.2 64-bit Release

处理 C++ 源文件...
--------
- C++ 编译器: C:\Program Files (x86)\Dev-Cpp\MinGW64\bin\g++.exe
- 命令: g++.exe "E:\test.cpp" -o "E:\test.exe" -std=c++11 ......................

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/488402
推荐阅读
相关标签
  

闽ICP备14008679号