anfängerprobleme mit sprintf
-
Ihr könnt mich gleich rausnehmen, meine Version war nicht großartig überdacht
-
gut, ich wollte hier vorher nur zeigen, dass es performancetechnischer quatsch ist, den stringstream bei jedem call zu bauen und wieder zu zerstoeren - was campers benchmark NOCH deutlicher zeigt. Besser als mit einem lookup table wirds wohl kaum gehen, revidierte fassung zwecks performanceschwanzvergleich folgt...
// edit:
std::string to_hex_string_swordfish_2( unsigned value ) { const char lookup[ ] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char buffer[ 16 ]; size_t i = 0; do { buffer[ i++ ] = lookup[ value % 16 ]; } while( value /= 16 ); return std::string( buffer, i ); }
Meine letzte Messung:
Swordfish: 596.335 Swordfish 2: 38.8694 Hacker: 1009.47 Ethon: 172.068 Ethon 2: 33.1679 Ethon 3: 50.1497 Incocnito: 69.6656
-
Bis darauf dass deins falsche Ergebnisse produziert.
int main() { std::cout << to_hex_string_swordfish_2(0xDEADBEEF) << std::endl; }
Ergibt
FEEBDAED
So ... damit das Ganze mal sinnvoll wird, Boost.Spirit ist doch bei soetwas immer der King. Jemand da, der das mit Spirit drauf hat?
-
std::string to_hex_string_karma(unsigned p_unsigned) { using boost::spirit::karma::generate; using boost::spirit::karma::hex; std::string result; std::back_insert_iterator<std::string> it(result); generate(it, hex(p_unsigned)); return result; }
Kompiliert mit MSVC++ 10.0
edit nochmal, hier die vergleichswerte. geht das noch besser in spirit?
32767 swordfish 12345678 3.356 hacker 12345678 9.658 ethon 12345678 0.546 ethon2 12345678 0.109 ethon3 12345678 0.078 <- king ethon4 2345678 0.172 incognito 12345678 0.218 karma 12345678 0.265
-
Ethon schrieb:
Bis darauf dass deins falsche Ergebnisse produziert.
ok, dann eben rückwärts (wenn Du nicht rückwärts lesen magst :p )
std::string to_hex_string( unsigned value ) { const char lookup[ ] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char buffer[ 16 ]; size_t i = 15; do buffer[ --i ] = lookup[ value % 16 ]; while( value /= 16 ); return std::string( buffer + i, 15 - i ); }
-
Warum macht ihr's euch immer so kompliziert mit dem lookup, wie wärs mit:
"0123456789ABCDEF"[value % 16]
-
314159265358979 schrieb:
Warum macht ihr's euch immer so kompliziert mit dem lookup, wie wärs mit:
"0123456789ABCDEF"[value % 16]
Sieht verdächtig einfach aus...
-
Nana, des passt schon. Ich find's halt ned schön.
-
Swordfish schrieb:
Nana, des passt schon. Ich find's halt ned schön.
In C++ ist schön, was komplex aussieht und dabei den Code verkürzt.
-
Es is wurscht. Der Compiler macht eh aus beidem des gleiche.
-
Ich hab nochmal was neues probiert.
std::string to_hex_string(long long val) { std::string hex; const char inv[] = "0123456789abcdef"; long long copy, size; copy = val; for(size = 0; copy /= 10; ++size); hex.resize(size); do { hex[size-((copy++)+1)] = inv[val%16]; } while(val /= 16); return hex; }
Ich komm zwar nicht an ethon oder camper ran, aber wenigstens check ich meinen Code
swordfish: 2000000 calls -> 1.065s
incocnito: 2000000 calls -> 0.701s
ethon3: 2000000 calls -> 0.509s
camper: 2000000 calls -> 0.555s//edit
static weggemacht
-
@Incocnito: Was sollen die static ohne const da? Die verhindern dass deine Funktion Thread Safe ist.
-
also bei mir (msvc cl v16) schaut's eher so aus:
swordfish 12345678 0.08 incognito 12345678 0.266
-
theta schrieb:
@Incocnito: Was sollen die static ohne const da? Die verhindern dass deine Funktion Thread Safe ist.
Wichtiger noch: sie sind der Geschwindigkeit wahrscheinlich auch nicht förderlich.
copy und size würde man normalerweise sowieso in Registern finden, und das static beim string verhindert zwar, dass dieser string jedesmal neu erzeugt werden muss, dafür wird beim return immer kopiert. Wäre der string dagegen automatisch, gäbe beim return nichts zu kopieren.
-
Nagut, dann ohne static.
@Swordfish
Scheint wohl so als wär was beim messen schiefgelaufen. Jetzt hab ich auch wieder solche Werteincocnito 12345678 0.722 swordfish 12345678 0.539 ethon3 12345678 0.516 camper 12345678 0.494
Ach, was solls...
Immer noch schneller als vorher.
-
Ich hätte noch Folgendes im Angebot:
template<typename T> std::string to_hex_string_tachyon(T val) { char const * lut = "0123456789abcdef"; T const mask(~((~T()) << 4)); std::string str(sizeof(val) * 2, 0); std::string::reverse_iterator i = str.rbegin(); while(val > 16) { *(i++) = lut[val & mask]; val >>= 4; } *i = lut[val & mask]; return str; }
-
Tachyon schrieb:
Ich hätte noch Folgendes im Angebot:
template<typename T> std::string to_hex_string_tachyon(T val) { char const * lut = "0123456789abcdef"; T const mask(~((~T()) << 4)); std::string str(sizeof(val) * 2, 0); std::string::reverse_iterator i = str.rbegin(); while(val > 16) { *(i++) = lut[val & mask]; val >>= 4; } *i = lut[val & mask]; return str; }
Da bleiben allerdings bei kleinen Zahlen führende '\0' drin stehen.
-
camper schrieb:
Da bleiben allerdings bei kleinen Zahlen führende '\0' drin stehen.
Da gabs hier schon mehrere Lösungen, wo das der Fall ist. Da haste Dich auch nicht beschwert.