printfを使わずに実数を表示する
printf("%f")より速くしようと思ってざっと作ったら、返ってprintfより遅かった。
std::stringなんか使っちゃ行かんのだな。printfの実装を参考にしよう。(それすらやってないんかいっ!)
#include <iostream> #include <string> #include <cmath> static std::string i2s(int value, int keta) { std::string str; str.reserve(keta); for (int index = 0; index < keta; ++index) { str.insert(0, 1, '0' + (value % 10)); value /= 10; } return str; } std::string f2s(double value, int keta, int precision = 6, bool sign = false, char padding = ' ', char separate = '.') { std::string result; result.reserve(keta); int part_int = std::floor(value); double part_float = value - part_int; int part_int_length = 0; for (int index = 1; index < part_int ; index *= 10) { part_int_length++; } int part_int_max; if (keta < precision) { part_int_max = 0; } else { part_int_max = keta - 1 - precision; } if (sign == true || value < 0) { if (value < 0) { result = '-'; } else { result = '+'; } part_int_max--; } for (int index = 0; index < part_int_max - part_int_length; ++index) { result += padding; } result += i2s(part_int, part_int_length) + separate; for (int index = 0; index < precision; index++) { part_float *= 10; } result += i2s((int)part_float, precision); return result; } template <int v1> class POWER10 { public: enum { value = POWER10<v1 - 1>::value * 10 }; }; template<> class POWER10<1> { public: enum { value = 10 }; }; template <int KETA, int PRESITION, bool SIGN = false, char PADDING = ' ', char SEPARATE = '.'> class FloatFormatterFix { private: static const int PART_INT_MAX = KETA - 1 - PRESITION; static const int PART_FLOAT_MULTI = POWER10<PRESITION>::value; public: FloatFormatterFix() {} public: std::string operator()(double value) const { std::string result; result.reserve(KETA); int part_int = floor(value); double part_float = value - part_int; int part_int_length = 0; for (int index = 1; index < part_int ; index *= 10) { part_int_length++; } if (SIGN == true || value < 0) { if (value < 0) { result = '-'; } else { result = '+'; } part_int_length++; } for (int index = 0; index < PART_INT_MAX - part_int_length; ++index) { result += PADDING; } result += i2s(part_int, part_int_length) + SEPARATE; result += i2s((int)(part_float * PART_FLOAT_MULTI), PRESITION); return result; } }; #include "sys/time.h" int main() { const int LOOP = 1000000; struct timeval start, end; gettimeofday(&start, NULL); printf("%ld.%06d\n", start.tv_sec, start.tv_usec); char buf[20]; for (int index = 0; index < LOOP; ++index) { snprintf(buf, 20, "%10.8f", 13.5343); } gettimeofday(&end, NULL); printf("%d.%06d\n", end.tv_sec, end.tv_usec); gettimeofday(&start, NULL); printf("%ld.%06d\n", start.tv_sec, start.tv_usec); for (int index = 0; index < LOOP; ++index) { std::string a = f2s(13.5343, 10,8); } gettimeofday(&end, NULL); printf("%d.%06d\n", end.tv_sec, end.tv_usec); gettimeofday(&start, NULL); printf("%ld.%06d\n", start.tv_sec, start.tv_usec); FloatFormatterFix<10, 8, false, ' ', ';'> formatter; for (int index = 0; index < LOOP; ++index) { std::string a = formatter(13.5343); } gettimeofday(&end, NULL); printf("%d.%06d\n", end.tv_sec, end.tv_usec); return 0; }