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:

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 = 100000;
static const size_t R = 7;

void PrintStats(std::vector<double> timings) {
    double fastest = std::numeric_limits<double>::max();

    std::cout << std::fixed << std::setprecision(2);
    std::cout << "[";
    for (size_t i = 1 ; i<timings.size()-1 ; ++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 = 1 ; i<timings.size() ; ++i) {
        sum += timings[i];
    }
    double avg = sum / static_cast<double>(timings.size()-1);

    sum = 0.0;
    for (size_t i = 1 ; i<timings.size() ; ++i) {
        timings[i] = pow(timings[i]-avg, 2);
        sum += timings[i];
    }
    double var = sum/(timings.size()-2);
    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 >= ‘0‘ && *p <= ‘9‘) {
        r = (r*10.0) + (*p - ‘0‘);
        ++p;
    }
    if (*p == ‘.‘) {
        double f = 0.0;
        int n = 0;
        ++p;
        while (*p >= ‘0‘ && *p <= ‘9‘) {
            f = (f*10.0) + (*p - ‘0‘);
            ++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=0 ; i<N ; ++i) {
        std::string y;
        if (i & 1) {
            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=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=0 ; 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=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=0 ; 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=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=0 ; i<nums.size() ; ++i) {
                double x = strtod(nums[i].c_str(), 0);
                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=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=0 ; 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=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=0 ; 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=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=0 ; 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=0 ; r<R ; ++r) {
            ticks start = getticks();
            for (size_t i=0 ; 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=0 ; r<R ; ++r) {
            ticks start = getticks();
            std::istringstream ss;
            for (size_t i=0 ; 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;
    }
}

时间: 2024-10-07 08:56:33

c++ stod很慢的相关文章

函数一直无法立即退出,在等待了大约30s后才能退出(QMulitHash释放不连续的内存需要很长世间,而这样设置局部变量后又无法避免这个问题)

局部变量使用对性能的影响以及进程的堆和栈: 由于在代码中我使用了QMulitHash<QString , LHFilteVersionItem> tmp;这一局部变量来保存某一目录下的文件,由于在写测试代码期间,我利用循环模拟了50万的数据序列化后保存在文件中,在运行期间我发现读取函数耗费很长的时间,而函数里面最耗时的读取操作也只花费了很短的时间,但是函数一直无法立即退出,在等待了大约30s后才能退出,相关代码如下: [cpp] view plain copy void LHTWORKFLOW

docker的存储结构,和以前有了很大不同

在网上学习这一块知识点时,有一个URL讲得很详细, docker 镜像与容器存储目录结构精讲 http://blog.csdn.net/wanglei_storage/article/details/50299491 但我在最新版的docker作验证时,发现早已物是人非,等以后用得着时,再仔细研究吧. 我作的截图如下: overlay里作image相关的存储, 而container目录里作run起来的docker容器的相关存储, 且两者之间,有uuid作对应. 在下图中已标明.

架构师写给工程师的一封信(很有价值)【转】

下面的邮件是某Architect发给他的Engineering团队的(来源),我觉得挺不错的,翻译过来,我相信我们所有的程序员都能从中学到很多东西.下面是这封邮件-- 每次当我开始做新的东西是我就会很兴奋.就算在软件圈里做了20年以后,每当开始新的旅程里,我都觉得我心中有一些东西不吐不快.这是我们大家一起的旅程.我强烈地相信我们详细规划的过程是很有乐趣的,富有挑战的和丰富多彩的.我想让这个旅程让你们难忘,并且能增添你们所有人的阅历. 这看起来有些唯心主义,不过,我想制订我的工作日程,我们的技术策

【算法整理】听说你写的算法很牛?-优质算法衡量标准探讨

引文 我有个朋友有算法强迫症,每次一看到别人写的算法,就有上去改的冲动,不然就会偏头疼,主要症结在于他认为别人写的算法不好,但是什么的算法可以评判为好,什么样的算法可以评判为不好?最近为了治愈他,我特地写了这篇文章. 算法的衡量从两个方向出发:时间复杂度和空间复杂度.本文主要是不讲具体算法,只将算法的衡量,重点讲解如何衡量算法的复杂度,解决平时见到的XX算法时间复杂是O(logn)O(logn),其中这个结果是怎么推导出来的?lognlogn是个什么玩意儿?,大写的OO是什么意思?为什么用这个符

Qt在Mac OS X下的编程环境搭建(配置Qt库和编译器,有图,很清楚)

尊重作者,支持原创,如需转载,请附上原地址:http://blog.csdn.net/libaineu2004/article/details/46234079 在Mac OS X下使用Qt开发,需要配置Qt库和编译器.编译器只能使用苹果公司自主研发的Clang.1.分别下载并安装XCode和Command Line Tools(必须安装),安装完毕后,Clang就有了. https://developer.apple.com/downloads/ 2.下载Qt并默认安装 http://down

沟通很重要

省赛结束了,但真正的工作才刚刚开始,省赛只是国赛的前期热身.学校已经放假了,而我并没有放假,我还在指导着即将参加国赛的同学们学习,一直到小年夜才能回家.谁说教师最幸福的就是有寒暑假,看着别的教师放寒暑假而自己不能休假,其实一点也不幸福. 省赛指导的那名需要我相信他的同学,今天和苏老师说他不想参加比赛了,着急找工作了,心思也不在这,状态也不好,学不进去了.我也知道他最近的状态,其实与其在这浪费时间,倒真不如去干点什么,可能省赛他就已经有这样的想法了,但碍于他曾经许下的承诺,一直也没说.苏老师这次跟

特朗普的中国命题作文,很可能以贸易战开头文图/陆飞

文图/陆飞 大选的结果让很多人意外,嘴硬的特朗普笑到了最后:希拉里也挺有风度,主动给特朗普打电话,这算是认输了. 对于选举结果的分析:为什么希拉里得势不得分,为什么特朗普成功上位,本文不再赘述.一直看热闹的我们,现在可以关心下一个话题,特朗普将怎么书写摆在他面前的其中一篇命题作文:中国. 1.复盘,反全球化和孤立主义帮了特朗普 有必要简单复盘特朗普获胜的关键,看一张图(蓝色-民主党·希拉里,红色-共和党·特朗普):   发文时,根据微软必应大数据,大选前全美共有18个"摇摆州"--其中

android:eclipse看着很舒服的字体和启动速度很快android模拟器

找了很久才找到这个字体 点击下载 下载后 在c盘windows/font文件夹下添加解压后的字体即可  然后重启eclipse  依次打开preference->General->appearance->Colors and Fonts-->Basic->Text Font->Edit 找到YaHei Consolas Hybrid 即可 如下: 感觉比以前看着舒服多了 还有eclipse的模拟器 启动慢  部署app的时候也慢 大家可以百度搜索genymotion官网

Gradle之旅-遇到的一个很简单但是用了很久才解决的问题

这个问题非常简单,但是对于我这个刚接触Gradle的人却是很难发现的一个错误,这个错误就是在使用gradle build的时候提示can not find tools.jar,我手动的添加了依赖,反复修改都没能解决这个错误,后来我无意中点到window->references->java->install jres发现这里定义的jre是jdk下的jre,不是jdk,然后我将定义的这个jre修改了为jdk的路径,然后重新运行gradle build,然后问题就解决了,虽然是个很小的问题,但