C performans meydan: tamsayı std::string dönüştürme
Kimse benim tamsayı performansını yenmek için std::string kod, aşağıda bağlantısı?
Zaten C std::string
, this one) gibi bir tamsayı dönüştürmek için nasıl açıklayan pek çok soru var ama çözümleri sağlanan hiçbiri verimli.
Burada bazı genel yöntemler, karşı yarışmak için bir derleme hazır kod:
- "C" kullanarak stringstream: *19.*
- SO-ers genellikle performans bilinçli tavsiye ederim sprintf,: http://ideone.com/82kwR
21*, boost::lexical_cast
*aksine kendi uygulaması (white paper) ve stringstream
ve sayısal ekleme operatörler kullanmaz. Gerçekten performansı this other question suggests that it's miserable çünkü karşılaştırıldığında, görmek istiyorum.
Ve masaüstü bilgisayarlarda rekabet ve gömülü sistemler üzerinde tam hızda çalışan bir yaklaşım gösterir, kendi katkısı olarak, algoritmalar tamsayı modül bağımlı aksine:
- Ben'in algoritmaları: http://ideone.com/SsEUW
Eğer bu kodu kullanmak istiyorsanız, basitleştirilmiş BSD Lisansı altında kullanılabilir (ticari kullanıma izin verilen, atıf gerekli) yapacağım. Sadece soruyorum.
Son olarak, 4* *işlevi standart olmayan ama yaygın olarak kullanılabilir.
- ltoa sürüm, bunu sağlayan bir derleyici olan herkes için (ideone değil): http://ideone.com/T5Wim
Cevap olarak benim performans ölçümleri kısa zamanda göndeririz.
Algoritmalar için kurallar
- En azından bir ondalık içine 32-bit işaretli ve işaretsiz tam bir dönüşüm için kod sağlar.
std::string
olarak çıktı üretir.- Diş çekme ve sinyalleri ile uyumlu olmayan hileler (örneğin, statik arabellekleri) hayır.
- ASCII karakter kümesi varsayabiliriz.
- Mutlak değer gösterilebilir bulunduğu iki a
INT_MIN
kodunuzu test etmek için emin makine tamamlayıcısı olacak. - İdeal olarak, bir çıkış olmalı karakter-için-karakteri ile özdeş kurallı C sürümünü kullanıyor
stringstream
, http://ideone.com/jh3Sa ama bir şey olduğu açıkça anlaşılır olarak doğru numara Tamam da. - YENİ: Derleyici ve iyileştirici seçenekleri tamamen devre dışı hariç) ne olursa olsun kullanabilirsiniz, ancak karşılaştırma için istediğiniz, kodu derlemek ve en az VC 2010 ve g altında doğru sonuçlar vermek gerekiyor .
Umut için Tartışma
Daha iyi algoritmalar yanı sıra, farklı platformlar ve Derleyiciler (hadi ölçü standart birim olarak MB/s işlem hacmi kullanın) bazı kriterler almak istiyorum. Sanırım bu kod benim için algoritma (biliyorum sprintf
referans alır bazı kısayollar -- şimdi sabit) iyi tanımlanmış davranış standart, en azından altında ASCII varsayım, ama eğer gördüğünüz herhangi bir tanımsız davranış veya girdiler için çıktı geçersiz, lütfen gelin.
Sonuç:
Farklı algoritmalar her g ve VC2010, std::string
farklı uygulamaları nedeniyle olası gerçekleştirin. VC2010 açıkça NRVO ile daha iyi bir iş, dönüş değeri gcc sadece yardım kurtulmak yok.
Kod büyüklük sırasına göre sprintf
daha iyi performans bulundu. ostringstream
arkasında 50 ve daha fazla bir faktör tarafından düşüyor.
Yarışmayı kazanan gcc benim kendi hızını 350% çalışan kod üreten user434507. Başka girdi YANİ toplum güçlükler nedeniyle kapandı.
Geçerli (final?) hız şampiyonu:
- Gcc için: 8 kat daha hızlı
sprintf
daha user434507, : http://ideone.com/0uhhX - Visual C için : Timo, 15 kat daha hızlı
sprintf
daha: http://ideone.com/VpKO3
CEVAP
#include <string>
const char digit_pairs[201] = {
"00010203040506070809"
"10111213141516171819"
"20212223242526272829"
"30313233343536373839"
"40414243444546474849"
"50515253545556575859"
"60616263646566676869"
"70717273747576777879"
"80818283848586878889"
"90919293949596979899"
};
std::string& itostr(int n, std::string& s)
{
if(n==0)
{
s="0";
return s;
}
int sign = -(n<0);
unsigned int val = (n^sign)-sign;
int size;
if(val>=10000)
{
if(val>=10000000)
{
if(val>=1000000000)
size=10;
else if(val>=100000000)
size=9;
else
size=8;
}
else
{
if(val>=1000000)
size=7;
else if(val>=100000)
size=6;
else
size=5;
}
}
else
{
if(val>=100)
{
if(val>=1000)
size=4;
else
size=3;
}
else
{
if(val>=10)
size=2;
else
size=1;
}
}
size -= sign;
s.resize(size);
char* c = &s[0];
if(sign)
*c='-';
c = size-1;
while(val>=100)
{
int pos = val % 100;
val /= 100;
*(short*)(c-1)=*(short*)(digit_pairs 2*pos);
c-=2;
}
while(val>0)
{
*c--='0' (val % 10);
val /= 10;
}
return s;
}
std::string& itostr(unsigned val, std::string& s)
{
if(val==0)
{
s="0";
return s;
}
int size;
if(val>=10000)
{
if(val>=10000000)
{
if(val>=1000000000)
size=10;
else if(val>=100000000)
size=9;
else
size=8;
}
else
{
if(val>=1000000)
size=7;
else if(val>=100000)
size=6;
else
size=5;
}
}
else
{
if(val>=100)
{
if(val>=1000)
size=4;
else
size=3;
}
else
{
if(val>=10)
size=2;
else
size=1;
}
}
s.resize(size);
char* c = &s[size-1];
while(val>=100)
{
int pos = val % 100;
val /= 100;
*(short*)(c-1)=*(short*)(digit_pairs 2*pos);
c-=2;
}
while(val>0)
{
*c--='0' (val % 10);
val /= 10;
}
return s;
}
Bu izin vermemek bellek erişir bu durumda *(short*)
ile ilk atama tarafsız bir segfault neden olur () tarafsız sistemler üzerinde patlayacak, ama çok güzel hizmetinde.
Bir şey std::string
kullanımını en aza indirmek için. (İronik, biliyorum.) Örneğin, Visual Studio, en std yöntemleri aramalar::dize derleyici seçenekleri /Ob2 belirtmek bile inlined değil. Bu yüzden bile bir şey gibi önemsiz bir çağrı std::string::clear()
, beklediğiniz için çok hızlı, alabileceği 100 clockticks bağlantı CRT olarak bir statik kütüphane kadar 300 clockticks bağlantı olarak DLL.
Aynı sebepten dolayı, başvurusu ile dönen bir ödev, bir yapıcı ve yıkıcı önler, çünkü daha iyidir.
c tamsayı->std::string dönüştürme. ...
Python string dönüştürme tamsayı?...
Dönüştürme python ikili tamsayı...
Liste< dönüştürme;Dize> String[] ...
Biçimlendirmek için en iyi yolu tamsay...