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 开发中很有用的效果,记 ...
随机推荐
- BeatifulSoup模块
一.介绍 Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你 ...
- hdu4612 卡cin e-DCC缩点
/* 给定无向图,求加入一条边后最少剩下多少桥 */ #include<bits/stdc++.h> using namespace std; #define maxn 200005 #d ...
- Vuex状态管理模式的面试题及答案
转载:点击查看原文 1.vuex有哪几种属性? 答:有五种,分别是 State. Getter.Mutation .Action. Module 2.vuex的State特性是? 答: 一.Vuex就 ...
- Python字符串编码转换
使用encode()方法编码 str.encode([encoding="utf-8"][,errors="strict"]) str:表示需要转换的字符串 e ...
- SSM 三大框架---事务处理
SSM 三大框架---事务处理 原创 2016年05月12日 20:57:03 标签: spring / J2EE / java / 框架 / 事务 7010 在学习三大框架的时候,老师说事务处理是最 ...
- war的创建
- IntelliJ Idea 配置Tomcat提示Port is not specified
修改Debug这里的端口就好了
- 期货大赛项目|二,DAL详解
接口层就不重点讲述了,直接DAL层 DAL层 using System; using System.Collections.Generic; using System.Linq; using Syst ...
- Codeforces Round #506 (Div. 3)
题解: div3水的没有什么意思 abc就不说了 d题比较显然的就是用hash 但是不能直接搞 所以我们要枚举他后面那个数的位数 然后用map判断就可以了 刚开始没搞清楚数据范围写了快速乘竟然被hac ...
- [WC2014]紫荆花之恋
题解: 首先考虑点分治 dis(i,u)+dis(i,v)<=value[u]+value[v] 移项就很容易发现用平衡树可以很简单的维护这个东西 但是有重复,需要在下一层的每个平衡树内减去这个 ...