C++ 将奇怪字符串转换为双C++;
我需要将数据从文件转换为双精度文件,有时数据的格式为:C++ 将奇怪字符串转换为双C++;,c++,regex,string,double,data-conversion,C++,Regex,String,Double,Data Conversion,我需要将数据从文件转换为双精度文件,有时数据的格式为: 0.3387000000D+02 0.6067999217D-02 0.5095000000D+01 0.4530799416D-01 0.1159000000D+01 0.2028219738D+00 0.3258000000D+00 0.5039029350D+00 0.1027000000D+00 0.3834209505D+00 您将如何处理这里的D 这是用D代替E的科学记数法 我想在这里使用std::regex,但我希
0.3387000000D+02 0.6067999217D-02
0.5095000000D+01 0.4530799416D-01
0.1159000000D+01 0.2028219738D+00
0.3258000000D+00 0.5039029350D+00
0.1027000000D+00 0.3834209505D+00
您将如何处理这里的D
这是用D
代替E
的科学记数法
我想在这里使用std::regex
,但我希望有一个更优雅的策略
如下所示:
std::regex rr( "((\\+|-)?[[:digit:]]+)(\\.(([[:digit]]+)?))?(d|D)((\\+|-)?)[[:digit:]]+)""?");
标准:正则表达式rr((\+)?[:位:]+)(\。([:位]]+)?(d | d)((\+)?)[:位:]+)”;
将
D
替换为E
,然后直接替换为:
你可以这样做
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cmath>
double string2double(std::string s)
{
// Find the index of scientific D
int indexD = s.find('D');
// separate the base from rest, start at 0 and go till index of D, without D
std::string number = s.substr(0, indexD);
//indexD+2 to ignore D and plus
std::string power = s.substr(indexD+2);
// do conversion from string to number
double rawNumber = std::stod(number);
double powerNumber = std::stod(power);
//test
std::cout << rawNumber << std::endl;
std::cout << powerNumber << std::endl;
//return
return rawNumber * std::pow(10, powerNumber);
}
int main()
{
std::string s = "0.3387000000D+02";
std::cout << string2double(s) << std::endl;
return 0;
}
#包括
#包括
#包括
#包括
#包括
双字符串双(标准::字符串s)
{
//查找科学数据索引
int indexD=s.find('D');
//将底部和其余部分分开,从0开始,直到索引为D,不带D
std::string number=s.substr(0,indexD);
//indexD+2忽略D和加号
std::字符串幂=s.substr(indexD+2);
//进行从字符串到数字的转换
double rawNumber=std::stod(编号);
双电源号=标准::stod(电源);
//试验
std::你能确定D和E的意思相同吗?你从哪里得到这些数据的?确认,它确实是E。这些数据来自量子化学软件包MOLPRO。我可以用E替换D,让标准转换函数处理其余的…@JohnFilleau Fortran使用D代替E。看,是的,这完全正确。MOLPRO是用谢谢你的链接!回复:“希望有一个更优雅的策略”--良好的直觉。正则表达式很少合适。我可以用一只手数一数我在StackOverflow上看到的关于正则表达式的问题的数量,其中正则表达式实际上是最好的解决方案。非常好!现在取决于程序的版本,只有有时字符串才有D。y也可以如果replace函数实际替换了任何内容,您可以修改代码以包含if
语句?@zstreet,当然。@zstreet,完成了,第一个选项只有在找到D
时才会替换,否则它什么也不做,但您有第二个选项。哦std::replace
的第一个选项如果不好,则什么也不做D
?我喜欢这样!谢谢!解析浮点文本有几个微妙的问题。这种蛮力代码大部分时间都可以工作,但它会导致许多边缘情况出错。例如,对于典型的64位双精度,最大指数是37。但是.00001e40
是一个有效的有限值;它只是写得很有趣。std::stod
可以处理这个问题;它产生的结果与std::stod(1.0e35)
相同。但是,如果您拆分指数,std::pow(10,40)
将得到无穷大。将无穷大乘以任何非零值将得到无穷大,这就是此函数将返回的.00001D40
。请注意,还有一个输入错误:s.substr(indexD+2)
应该是s.substr(indexD+1)
。该代码与main
中的测试值一起工作,因为指数是02
;如果指数是12
,结果将是错误的。这里的寓意是:在处理浮点数学时不要相信你的直觉。你的直觉来自实数的经验;浮点数不是实数s、 而且你(和我的!)的直觉经常是错误的。谢谢你的评论,皮特!很高兴知道
bool isD(char c) {
return c == 'D';
}
std::string s = "0.3387000000D+02";
std::replace_if( s.begin(), s.end(), isD, 'E');
std::cout << std::stod(s);
33.87
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cmath>
double string2double(std::string s)
{
// Find the index of scientific D
int indexD = s.find('D');
// separate the base from rest, start at 0 and go till index of D, without D
std::string number = s.substr(0, indexD);
//indexD+2 to ignore D and plus
std::string power = s.substr(indexD+2);
// do conversion from string to number
double rawNumber = std::stod(number);
double powerNumber = std::stod(power);
//test
std::cout << rawNumber << std::endl;
std::cout << powerNumber << std::endl;
//return
return rawNumber * std::pow(10, powerNumber);
}
int main()
{
std::string s = "0.3387000000D+02";
std::cout << string2double(s) << std::endl;
return 0;
}