質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Boost

Boost (ブースト)は、C++の先駆的な開発者のコミュニティ、 またそのコミュニティによって公開されているオープンソースライブラリのことを指します。

Q&A

解決済

1回答

3804閲覧

chronoの実装

katahiromz

総合スコア186

C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Boost

Boost (ブースト)は、C++の先駆的な開発者のコミュニティ、 またそのコミュニティによって公開されているオープンソースライブラリのことを指します。

0グッド

0クリップ

投稿2016/10/29 08:13

編集2016/10/30 03:10

こんにちは、コンピュータ研究家の片山博文MZと言います。
現在、C++11とBoostをまねて、Unboostというライブラリを作っています。

Unboost
https://github.com/katahiromz/unboost

Unboostのchronoの実装ですが、うまく動作しない箇所があります。

これが現在のchronoの実装です。
https://github.com/katahiromz/unboost/blob/master/unboost/chrono.hpp

これがサンプルchrono.cppです。
https://github.com/katahiromz/unboost/blob/master/samples/chrono.cpp

で、サンプルchronoのコンパイルを行うと、ビルドは成功します。
ビルドとテストの様子

しかし、テストの出力を見ると、「years since epoch」や「yesterday, years since epoch」がマイナスの値になってしまいます。多分、time_pointのどこかの計算が間違えていると思います。

問題の箇所は、chrono.cppの305行目以降になります。
https://github.com/katahiromz/unboost/blob/master/samples/chrono.cpp#L305

修正方法を教えて下さい。よろしくお願いします。

(追記)
関数を修正しました。

C++

1// NOTE: epoch is 1970.01.01 2#ifdef UNBOOST_USE_WIN32_CHRONO 3 typedef ratio<1, 10000000> _nano100; 4 typedef chrono::duration<_int64_t, _nano100> _system_duration; 5 typedef chrono::duration<_int64_t, nanoseconds> _steady_duration; 6 inline _int64_t _get_system_clock_time(void) { 7 // in 100-nanoseconds 8 FILETIME ft; 9 ::GetSystemTimeAsFileTime(&ft); 10 LONGLONG n = ft.dwHighDateTime; 11 n <<= 32; 12 n |= ft.dwLowDateTime; 13 return n - 0x19DB1DED53E8000; 14 } 15 inline LARGE_INTEGER *_get_perf_freq() { 16 static LARGE_INTEGER s_freq; 17 if (!::QueryPerformanceFrequency(&s_freq)) 18 assert(0); 19 return &s_freq; 20 } 21 inline _int64_t _get_steady_clock_time(void) { 22 // in nanoseconds 23 static LARGE_INTEGER *s_pfreq = _get_perf_freq(); 24 LARGE_INTEGER counter; 25 ::QueryPerformanceCounter(&counter); 26 return counter.QuadPart * (1000000000 / s_pfreq->QuadPart); 27 } 28#elif defined(UNBOOST_USE_POSIX_CHRONO) 29 typedef chrono::duration<_int64_t, microseconds> _system_duration; 30 typedef chrono::duration<_int64_t, microseconds> _steady_duration; 31 inline _int64_t _get_system_clock_time(void) { 32 // in microseconds 33 struct timeval tv; 34 struct timezone tz; 35 gettimeofday(&tv); 36 return tv.tv_sec * 1000000 + tv.tv_usec; 37 } 38 inline _int64_t _get_steady_clock_time(void) { 39 // in microseconds 40 struct timeval tv; 41 struct timezone tz; 42 gettimeofday(&tv); 43 return tv.tv_sec * 1000000 + tv.tv_usec; 44 }

でもduration_castがおかしいのか、変な値が出力されます。

text

1katahiromz@katahiromz-PC MINGW32 /c/Users/katahiromz/Desktop/cc/unboost 2$ g++ -DUNBOOST_NO_CXX11 -I. samples/chrono.cpp 3 4katahiromz@katahiromz-PC MINGW32 /c/Users/katahiromz/Desktop/cc/unboost 5$ ./a.exe 6chrono 7... 8epoch: Thu Jan 01 00:00:00 1970 9today: Sun Oct 30 02:53:54 2016 10years since epoch: 7293107 11yesterday, years since epoch: 7293088 12all times: 13Sun Oct 30 01:48:17 2016 14Sun Oct 30 00:42:41 2016 15Sun Oct 30 03:59:31 2016 16earliest: 17Sun Oct 30 00:42:41 2016

「years since epoch」は2016-1970=46で46年間のはずです。何が間違えているのでしょうか?
また、「all times」の部分は、24時間単位で変化しているはずなのに、分や秒が変わっています。該当のソースは、下記の通りです。

C++

1// FIXME: 2{ 3 using namespace unboost::chrono; 4 using unboost::ratio; 5 time_point<system_clock> p1, p2, p3; 6 typedef duration<unboost::_int64_t, ratio<3600 * 24 * 365> > years; 7 8 p2 = system_clock::now(); 9 p3 = p2 - hours(24); 10 11 std::time_t epoch_time = system_clock::to_time_t(p1); 12 std::cout << "epoch: " << std::asctime(std::gmtime(&epoch_time)); 13 14 std::time_t today_time = system_clock::to_time_t(p2); 15 std::cout << "today: " << std::asctime(std::gmtime(&today_time)); 16 17 std::cout << "years since epoch: " 18 << duration_cast<years>(p2.time_since_epoch()).count() 19 << '\n'; 20 std::cout << "yesterday, years since epoch: " 21 << duration_cast<years>(p3.time_since_epoch()).count() 22 << '\n'; 23} 24{ 25 using namespace unboost::chrono; 26 time_point<system_clock> now = system_clock::now(); 27 std::vector<time_point<system_clock>> times; 28 times.push_back(now - hours(24)); 29 times.push_back(now - hours(48)); 30 times.push_back(now + hours(24)); 31 32 time_point<system_clock> earliest = time_point<system_clock>::max(); 33 34 std::cout << "all times:\n"; 35 for (const auto &time : times) { 36 std::time_t t = system_clock::to_time_t(time); 37 std::cout << std::asctime(std::gmtime(&t)); 38 39 if (time < earliest) earliest = time; 40 } 41 42 std::time_t t = system_clock::to_time_t(earliest); 43 std::cout << "earliest:\n"; 44 std::cout << std::asctime(std::gmtime(&t)) << std::endl; 45}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

#ifdef UNBOOST_USE_WIN32_CHRONO inline double _get_clock_time(void) { FILETIME ft; ::GetSystemTimeAsFileTime(&ft); LONGLONG n = ((LONGLONG)ft.dwHighDateTime << 32) + ft.dwLowDateTime; return ((n - 116444736000000000) / 10000000.0); } #elif defined(UNBOOST_USE_POSIX_CHRONO) inline double _get_clock_time(void) { struct timeval tv; struct timezone tz; gettimeofday(&tv); return tv.tv_sec + tv.tv_usec / 1000000.0; }

なぜにdoubleにキャストする?無駄に精度を落とすことなかれ。

あと
https://gist.github.com/t-mat/3763854
を読むべし

それから
steady_clock
にはQueryPerformanceFrequencyを使うこと。時間が逆行しないことを保証する必要がある。
high_resolution_clock
も精度的にQueryPerformanceFrequencyを使うこと。


それはそうと、boost.testでもiutestでもなんでもいいから、C++11が使える環境でSTLの実装を利用してテストケースを書くべし。

投稿2016/10/29 10:23

編集2016/10/29 10:35
yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

katahiromz

2016/10/30 03:52

無事解決しました。_gcd関数の精度の問題でした。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問