anfängerprobleme mit sprintf
-
Teste doch nochmal das hier:
template<typename CharT> std::basic_string<CharT> to_hex_string(unsigned value) { typedef std::basic_string<CharT> string_type; string_type result(sizeof(value) * 2, 0); typename string_type::reverse_iterator iter = result.rbegin(); while(value > 16) { unsigned cur = value % 16; *iter = cur < 10 ? CharT('0') + cur : CharT('A') + cur - 10; ++iter; value /= 16; } *iter = value < 10 ? CharT('0') + value : CharT('A') + value - 10; return result; }
-
camper schrieb:
Hat zwar nichts mit dem Thema zu tun... aber
#define WIN32_LEAN_AND_MEAN
nachdem du <windows.h> bereits eingebunden hast, scheint mir sinnlos zu sein.
Äh, ja
Ethon schrieb:
Teste doch nochmal das hier:
Ethon: 33.6387
-
Danke, wundert mich gerade etwas. Hat meine Implementierung irgendeine Macke? Denn std::to_string (C++11) schlage ich um mehr als das Doppelte.
So siehts jetzt aus:
template<typename CharT, int Base> std::basic_string<CharT> to_string(unsigned value) { CharT const lookup[] = { CharT('0'), CharT('1'), CharT('2'), CharT('3'), CharT('4'), CharT('5'), CharT('6'), CharT('7'), CharT('8'), CharT('9'), CharT('A'), CharT('B'), CharT('C'), CharT('D'), CharT('E'), CharT('F') }; typedef std::basic_string<CharT> string_type; string_type result(sizeof(value) * 2, 0); typename string_type::reverse_iterator iter = result.rbegin(); while(value > Base) { *iter = lookup[value % Base]; ++iter; value /= Base; } *iter = lookup[value]; return result; }
Kompilieren tu ich das Ganze mit dem GCC und -O3.
Edit: Ahhh, ich seh grad, wenn die Zahlen zu klein sind funktionierts nicht. Hmm ...
-
Tja, Ethon, du bist ein Genius.
-
Hacker schrieb:
Tja, Ethon, du bist ein Genius.
Lässt sich doch fixen. Bei 2x Speedup sollte das danach immer noch deutlich schneller sein. Mal ausprobieren.
-
Ethon schrieb:
Hacker schrieb:
Tja, Ethon, du bist ein Genius.
Lässt sich doch fixen. Bei 2x Speedup sollte das danach immer noch deutlich schneller sein. Mal ausprobieren.
Denkst du, dass, wenn du's an ISO/IEC schickst, sie es dann in den nächsten aufnehmen?
-
template<typename CharT, unsigned Base> std::basic_string<CharT> to_string(unsigned value) { static_assert(Base <= 16, "Unsupported Base"); CharT const lookup[] = { CharT('0'), CharT('1'), CharT('2'), CharT('3'), CharT('4'), CharT('5'), CharT('6'), CharT('7'), CharT('8'), CharT('9'), CharT('A'), CharT('B'), CharT('C'), CharT('D'), CharT('E'), CharT('F') }; std::array<CharT, std::numeric_limits<unsigned>::digits> buffer; auto iter = buffer.rbegin(); while(value > Base) { *iter = lookup[value % Base]; ++iter; value /= Base; } *iter = lookup[value]; return std::basic_string<CharT>(&(*iter), buffer.end()); }
Gefixt und noch schneller geworden.
Zum Konvertieren von 10.000.000 rand Werten braucht meine Funktion
real 0m11.909s
user 0m11.905s
sys 0m0.000sund std::to_string
real 0m26.853s
user 0m26.838s
sys 0m0.004sAlso, was ist der Unterschied?
-
Ethon!! Welchen Compiler benutzt du? Alter, mein GCC 4.7 meckert, dass to_string nicht deklariert ist (obwohl ich string implementiere). Was soll ich nur tun :schluchz:
-
Gcc 4.6.1
Kompiliert mit:
g++ -o test -O3 -march=native -std=c++0x test.cpp
Für std::to_string brauchst du <string> und den C++11 Switch.
-
Ethon schrieb:
Gcc 4.6.1
Kompiliert mit:
g++ -o test -O3 -march=native -std=c++0x test.cpp
Für std::to_string brauchst du <string> und den C++11 Switch.
Funktioniert immer noch nicht.
-
Ethon schrieb:
return std::basic_string<CharT>(&(*iter), buffer.end());
Bist Du sicher, daß basic_string diesen c-tor haben muss?
-
[quote="Swordfish"]
Ethon schrieb:
return std::basic_string<CharT>(&(*iter), buffer.end());
Bist Du sicher, daß basic_string diesen c-tor haben muss?
Jeder Container lässt sich garantiert mit einem Inputiteratorenpaar konstruieren, bin mir zu 100% sicher dass es auch für std::basic_string vorgeschrieben ist, man findet ihn auch in jeder C++ Referenz.
-
Ich hab auch noch eine Idee:
#include <algorithm> std::string to_hex_string(unsigned value) { static std::string hex; hex.clear(); do { if(value%16 >= 0 && value%16 < 10) hex += value%16 + '0'; else if(value%16 > 9 && value%16 < 17) hex += value%16 + 55; } while(value /= 16); std::reverse(hex.begin(), hex.end()); return hex; }
Swordfish: 414.683
Hacker: 1317.21
Meine: 284.66Außerdem braucht bei mir
std::string to_hex_string(unsigned value) { char buffer[sizeof(value) * 2 + 1]; sprintf(buffer,"%x", value); return std::string(buffer); }
sogar mit 2370.08 deutlich länger (mit -O3)...
-
Aaaaahh! Jetz' seh' ich's erst,
iter
ist auto ... da kann ich mein msvc stecken lassen ...*umschreibengeh'*
Incocnito schrieb:
Außerdem braucht bei mir [sprintf] sogar mit 2370.08 deutlich länger (mit -O3)...
Grenzt an unmöglichkeit. Maschine?
// edit:
Swordfish: 594.549 Hacker: 1022.05 Ethon: 176.339 Ethon 2: 34.5288 Ethon 3: 49.962 Incocnito: 71.5127
// edit: Ethon 3 mit
return std::basic_string<CharT, std::char_traits< CharT > >( iter.base( ), buffer.end( ) );
-
Swordfish schrieb:
Ethon schrieb:
return std::basic_string<CharT>(&(*iter), buffer.end());
Bist Du sicher, daß basic_string diesen c-tor haben muss?
Er meint sicher
return std::basic_string<CharT>(iter.base(), buffer.end());
-
Ich hab Code::Blocks mit dem GCC 4.6.2 auf Windows 7 64 bit, duo 2.3ghz.
Das hier kompiliert
Und bekomm als Ausgabe
Ethon: ~2300
Ist irgendwie komisch.
-
[quote="Ethon"]
Swordfish schrieb:
Ethon schrieb:
return std::basic_string<CharT>(&(*iter), buffer.end());
Bist Du sicher, daß basic_string diesen c-tor haben muss?
Jeder Container lässt sich garantiert mit einem Inputiteratorenpaar konstruieren, bin mir zu 100% sicher dass es auch für std::basic_string vorgeschrieben ist, man findet ihn auch in jeder C++ Referenz.
Nur ist das da kein Inputiteratorenpaar.
-
[quote="Michael E."]
Ethon schrieb:
Swordfish schrieb:
Ethon schrieb:
return std::basic_string<CharT>(&(*iter), buffer.end());
Bist Du sicher, daß basic_string diesen c-tor haben muss?
Jeder Container lässt sich garantiert mit einem Inputiteratorenpaar konstruieren, bin mir zu 100% sicher dass es auch für std::basic_string vorgeschrieben ist, man findet ihn auch in jeder C++ Referenz.
Nur ist das da kein Inputiteratorenpaar.
Ein Zeiger unterstützt alle Operationen, die ein Inputiterator können muss, ist von daher also kompatibel.
Swordfish: 594.549 Hacker: 1022.05 Ethon: 176.339 Ethon 2: 34.5288 Ethon 3: 49.962 Incocnito: 71.5127
Interessant dass bei dir die dritte Version langsamer ist, beim GCC war sie schneller.
Er meint sicher
return std::basic_string<CharT>(iter.base(), buffer.end());
Was es nicht alles gibt, danke.
-
Ethon schrieb:
Ein Zeiger unterstützt alle Operationen, die ein Inputiterator können muss, ist von daher also kompatibel.
template<class InputIterator> basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator());
Also müssen die beiden Parameter denselben Typ haben. Da Paragraph 21.4.5 sagt, dass string::iterator implementation defined ist mit Bezug auf Paragraph 23.2, darfst du dann die Stelle suchen, an der steht, dass string::iterator einen nicht expliziten einstelligen Konstruktor mit einem Pointer als Parameter hat (keine Ahnung, obs die Garantie gibt, bin aber zu faul zum Suchen).
-
Lustig. Wenn ich diesen Code hier kompiliere, erhalte ich folgende Ergebnisse unterm GCC (-O3):
Swordfish: 418.613
Hacker: 1298.35
Ethon: 2315.44
Inco: 287.326Und wenn ich das ganze mit VS-2010 Express mache, hing mein Computer erstmal ne ganze Weile komplett, und dann hatte ich diese Ausgabe:
Swordfish: 18503.3
Hacker: 36503.5
Ethon: 5813.38
Inco: 12065.5Kann mir das jemand erklären