c++ stod很慢
C++ Convert String to Double Speed
(There is also a string-to-int performance test.)
A performance benchmark of which method is faster of converting an std::string to a double. The goal is ending up with a double of the value represented in an std::string.
The tested methods are:
- a hand-written naive loop
- atof()
- strtod()
- sscanf()
- boost::lexical_cast<double>()
- boost::spirit::qi::parse()
- std::stringstream
- std::stringstream, reusing the object
Source for the test is at speed-string-to-double.cpp with cycle.h.
The compilers are Microsoft Visual C++ 2010 with _SECURE_SCL disabled, GNU g++ 4.6.0, and LLVM clang++ from Arch.
Tests were run for converting 100000 string containing doubles in the range +/- 99999.99999. The result for the naive loop and atof() are set as the baseline 100% and the other numbers is time spent relative to those. The naive loop wins by a large margin, but Boost.Spirit is the fastest correct implementation.
Windows: MSVC++ 2010
- Compiler: MSVC++ 2010 _SECURE_SCL=0
- Arch: Windows 7 64 bit, 1.60GHz Core i7 Q720, 8 GiB RAM
| VC++ 2010 | Ticks | Relative to naive | Relative to atof() |
|---|---|---|---|
| naive | 4366220 | 1.00 | 0.05 |
| atof() | 82732774 | 18.95 | 1.00 |
| strtod() | 83189198 | 19.05 | 1.01 |
| sscanf() | 168568387 | 38.61 | 2.04 |
| spirit qi | 18932917 | 4.34 | 0.23 |
| lexical_cast | 332374407 | 76.12 | 4.02 |
| stringstream | 361943816 | 82.90 | 4.37 |
| stringstream reused | 240848392 | 55.16 | 2.91 |
Linux: GNU g++ 4.6.0
- Compiler: GNU g++ 4.6.0 -O3
- Arch: VirtualBox on the Windows machine, VT-x, Arch Linux, kernel 2.6.38-ARCH, 1 GiB RAM
| g++ 4.6.0 | Ticks | Relative to naive | Relative to atof() |
|---|---|---|---|
| naive | 4656159 | 1.00 | 0.15 |
| atof() | 30605490 | 6.57 | 1.00 |
| strtod() | 30963926 | 6.65 | 1.01 |
| sscanf() | 56235197 | 12.08 | 1.84 |
| spirit qi | 20731062 | 4.45 | 0.68 |
| lexical_cast | 139521406 | 29.96 | 4.56 |
| stringstream | 184723298 | 39.67 | 6.04 |
| stringstream reused | 100905407 | 21.67 | 3.30 |
Linux: LLVM clang++ 2.9
- Compiler: clang++ 2.9 -O3
- Arch: VirtualBox on the Windows machine, VT-x, Arch Linux, kernel 2.6.38-ARCH, 1 GiB RAM
| clang++ 2.9 | Ticks | Relative to naive | Relative to atof() |
|---|---|---|---|
| naive | 6804881 | 1.00 | 0.22 |
| atof() | 30829865 | 4.53 | 1.00 |
| strtod() | 30871514 | 4.54 | 1.00 |
| sscanf() | 57903993 | 8.51 | 1.88 |
| spirit qi | 24411041 | 3.59 | 0.79 |
| lexical_cast | 149339833 | 21.95 | 4.84 |
| stringstream | 191239066 | 28.10 | 6.20 |
| stringstream reused | 100461405 | 14.76 | 3.26 |
#ifdef _MSC_VER
#define _SECURE_SCL 0
#define _CRT_SECURE_NO_DEPRECATE 1
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
#define NOMINMAX
#endif #include <cstdlib>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <cmath>
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
#include <sstream>
#include <boost/lexical_cast.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include "cycle.h" static const size_t N = ;
static const size_t R = ; void PrintStats(std::vector<double> timings) {
double fastest = std::numeric_limits<double>::max(); std::cout << std::fixed << std::setprecision();
std::cout << "[";
for (size_t i = ; i<timings.size()- ; ++i) {
fastest = std::min(fastest, timings[i]);
std::cout << timings[i] << ",";
}
std::cout << timings.back();
std::cout << "]"; double sum = 0.0;
for (size_t i = ; i<timings.size() ; ++i) {
sum += timings[i];
}
double avg = sum / static_cast<double>(timings.size()-); sum = 0.0;
for (size_t i = ; i<timings.size() ; ++i) {
timings[i] = pow(timings[i]-avg, );
sum += timings[i];
}
double var = sum/(timings.size()-);
double sdv = sqrt(var); std::cout << " with fastest " << fastest << ", average " << avg << ", stddev " << sdv;
} double naive(const char *p) {
double r = 0.0;
bool neg = false;
if (*p == '-') {
neg = true;
++p;
}
while (*p >= '' && *p <= '') {
r = (r*10.0) + (*p - '');
++p;
}
if (*p == '.') {
double f = 0.0;
int n = ;
++p;
while (*p >= '' && *p <= '') {
f = (f*10.0) + (*p - '');
++p;
++n;
}
r += f / std::pow(10.0, n);
}
if (neg) {
r = -r;
}
return r;
} int main() {
std::vector<std::string> nums;
nums.reserve(N);
for (size_t i= ; i<N ; ++i) {
std::string y;
if (i & ) {
y += '-';
}
y += boost::lexical_cast<std::string>(i);
y += '.';
y += boost::lexical_cast<std::string>(i);
nums.push_back(y);
} {
double tsum = 0.0;
std::vector<double> timings;
timings.reserve(R);
for (size_t r= ; r<R ; ++r) {
ticks start = getticks();
for (size_t i= ; i<nums.size() ; ++i) {
double x = naive(nums[i].c_str());
tsum += x;
}
ticks end = getticks();
double timed = elapsed(end, start);
timings.push_back(timed);
} std::cout << "naive: ";
PrintStats(timings);
std::cout << std::endl;
std::cout << tsum << std::endl;
} {
double tsum = 0.0;
std::vector<double> timings;
timings.reserve(R);
for (size_t r= ; r<R ; ++r) {
ticks start = getticks();
for (size_t i= ; i<nums.size() ; ++i) {
double x = atof(nums[i].c_str());
tsum += x;
}
ticks end = getticks();
double timed = elapsed(end, start);
timings.push_back(timed);
} std::cout << "atof(): ";
PrintStats(timings);
std::cout << std::endl;
std::cout << tsum << std::endl;
} {
double tsum = 0.0;
std::vector<double> timings;
timings.reserve(R);
for (size_t r= ; r<R ; ++r) {
ticks start = getticks();
for (size_t i= ; i<nums.size() ; ++i) {
double x = strtod(nums[i].c_str(), );
tsum += x;
}
ticks end = getticks();
double timed = elapsed(end, start);
timings.push_back(timed);
} std::cout << "strtod(): ";
PrintStats(timings);
std::cout << std::endl;
std::cout << tsum << std::endl;
} {
double tsum = 0.0;
std::vector<double> timings;
timings.reserve(R);
for (size_t r= ; r<R ; ++r) {
ticks start = getticks();
for (size_t i= ; i<nums.size() ; ++i) {
double x = 0.0;
sscanf(nums[i].c_str(), "%lf", &x);
tsum += x;
}
ticks end = getticks();
double timed = elapsed(end, start);
timings.push_back(timed);
} std::cout << "sscanf(): ";
PrintStats(timings);
std::cout << std::endl;
std::cout << tsum << std::endl;
} {
double tsum = 0.0;
std::vector<double> timings;
timings.reserve(R);
for (size_t r= ; r<R ; ++r) {
ticks start = getticks();
for (size_t i= ; i<nums.size() ; ++i) {
double x = boost::lexical_cast<double>(nums[i]);
tsum += x;
}
ticks end = getticks();
double timed = elapsed(end, start);
timings.push_back(timed);
} std::cout << "lexical_cast: ";
PrintStats(timings);
std::cout << std::endl;
std::cout << tsum << std::endl;
} {
using boost::spirit::qi::double_;
using boost::spirit::qi::parse;
double tsum = 0.0;
std::vector<double> timings;
timings.reserve(R);
for (size_t r= ; r<R ; ++r) {
ticks start = getticks();
for (size_t i= ; i<nums.size() ; ++i) {
double x = 0.0;
char const *str = nums[i].c_str();
parse(str, &str[nums[i].size()], double_, x);
tsum += x;
}
ticks end = getticks();
double timed = elapsed(end, start);
timings.push_back(timed);
} std::cout << "spirit qi: ";
PrintStats(timings);
std::cout << std::endl;
std::cout << tsum << std::endl;
} {
double tsum = 0.0;
std::vector<double> timings;
timings.reserve(R);
for (size_t r= ; r<R ; ++r) {
ticks start = getticks();
for (size_t i= ; i<nums.size() ; ++i) {
std::istringstream ss(nums[i]);
double x = 0.0;
ss >> x;
tsum += x;
}
ticks end = getticks();
double timed = elapsed(end, start);
timings.push_back(timed);
} std::cout << "stringstream: ";
PrintStats(timings);
std::cout << std::endl;
std::cout << tsum << std::endl;
} {
double tsum = 0.0;
std::vector<double> timings;
timings.reserve(R);
for (size_t r= ; r<R ; ++r) {
ticks start = getticks();
std::istringstream ss;
for (size_t i= ; i<nums.size() ; ++i) {
ss.str(nums[i]);
ss.clear();
double x = 0.0;
ss >> x;
tsum += x;
}
ticks end = getticks();
double timed = elapsed(end, start);
timings.push_back(timed);
} std::cout << "stringstream reused: ";
PrintStats(timings);
std::cout << std::endl;
std::cout << tsum << std::endl;
}
}
c++ stod很慢的更多相关文章
- 看到了必须要Mark啊,最全的编程中英文词汇对照汇总(里面有好几个版本的,每个版本从a到d的顺序排列)
java: 第一章: JDK(Java Development Kit) java开发工具包 JVM(Java Virtual Machine) java虚拟机 Javac 编译命令 java ...
- C++11特性中的stoi、stod
本文摘录柳神笔记: 使⽤ stoi . stod 可以将字符串 string 转化为对应的 int 型. double 型变量,这在字符串处理的很 多问题中很有帮助-以下是示例代码和⾮法输⼊的处理 ...
- 很多人很想知道怎么扫一扫二维码就能打开网站,就能添加联系人,就能链接wifi,今天说下这些格式,明天做个demo
有些功能部分手机不能使用,网站,通讯录,wifi基本上每个手机都可以使用. 在看之前你可以扫一扫下面几个二维码先看看效果: 1.二维码生成 网址 (URL) 包含网址的 二维码生成 是大家平时最常接触 ...
- 再谈C#采集,一个绕过高强度安全验证的采集方案?方案很Low,慎入
说起采集,其实我是个外行,以前拔过阿里巴巴的客户数据,在我博客的文章:C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子) 中,介绍过采集用的工具,其实很Low的,分析 ...
- [.NET] 打造一个很简单的文档转换器 - 使用组件 Spire.Office
打造一个很简单的文档转换器 - 使用组件 Spire.Office [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6024827.html 序 之前,& ...
- ElasticSearch 5学习(5)——第一个例子(很实用)
想要知道ElasticSearch是如何使用的,最快的方式就是通过一个简单的例子,第一个例子将会包括基本概念如索引.搜索.和聚合等,需求是关于公司管理员工的一些业务. 员工文档索引 业务首先需要存储员 ...
- 11 个很少人知道但很有用的 Linux 命令
Linux命令行吸引了大多数Linux爱好者.一个正常的Linux用户一般掌握大约50-60个命令来处理每日的任务.Linux命令和它们的转换对于Linux用户.Shell脚本程序员和管理员来说是最有 ...
- 在网站开发中很有用的8个 jQuery 效果【附源码】
jQuery 作为最优秀 JavaScript 库之一,改变了很多人编写 JavaScript 的方式.它简化了 HTML 文档遍历,事件处理,动画和 Ajax 交互,而且有成千上万的成熟 jQuer ...
- Web 开发中很实用的10个效果【附源码下载】
在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多,但是一时半会又想不起来在哪,所以养成知识整理的习惯是很有必要的.这篇文章给大家推荐10个在 Web 开发中很有用的效果,记 ...
随机推荐
- Nginx详解九:Nginx基础篇之Nginx的访问控制
基于IP的访问控制:http_access_module 不允许指定网段的用户访问:配置语法:deny address | CIDR | unix: | all;默认状态:-配置方法:http.ser ...
- python基础复习
复习-基础 一.review-base 其他语言吗和python的对比 c vs Python c语言是python的底层实现,解释器就是由python编写的. c语言开发的程序执行效率高,开发现率低 ...
- SVN重新设置用户名和密码
在第一次使用TortoiseSVN从服务器CheckOut的时候,会要求输入用户名和密码,这时输入框下面有个选项是保存认证信息,如果选了这个选项,那么以后就不用每次都输入一遍用户名密码了. 不过,如果 ...
- 如何使用Scrapy框架实现网络爬虫
现在用下面这个案例来演示如果爬取安居客上面深圳的租房信息,我们采取这样策略,首先爬取所有租房信息的链接地址,然后再根据爬取的地址获取我们所需要的页面信息.访问次数多了,会被重定向到输入验证码页面,这个 ...
- Python模块的导入以及软件开发规范
Python文件的两种用途 1 . 当脚本直接使用,直接当脚本运行调用即可 def func(): print("from func1") func() 2 . 当做模块被导入使用 ...
- 使用docker方式安装etcd集群,带TLS证书
网上文档也多,安装的时候,还是踩了几个坑. 现在作一个安装记录吧. 1,先作自签名的证书ca-csr.json(为了和k8s共用根证书,可能将信息调为k8s). { "CN": & ...
- 一脸懵逼学习keepalived(对Nginx进行热备)
1:Keepalived的官方网址:http://www.keepalived.org/ 2:Keepalived:可以实现高可靠: 高可靠的概念: HA(High Available), 高可用性集 ...
- 使用SecureCRT脚本备份网络设备配置的一点感悟
https://blog.csdn.net/qq_25294171/article/details/85158458
- URL地址编码和解码
0. 参考 [整理]关于http(GET或POST)请求中的url地址的编码(encode)和解码(decode) python3中的urlopen对于中文url是如何处理的? 中文URL的编码问题 ...
- 分布式系统的BASE理论
一.BASE理论 eBay的架构师Dan Pritchett源于对大规模分布式系统的实践总结,在ACM上发表文章提出BASE理论,BASE理论是对CAP理论的延伸,核心思想是即使无法做到强一致性(St ...