2011-07-19 15 views
8

W jaki sposób liczby całkowite i łańcuchy są porównywane na niskim poziomie? Jak zawsze, gdy używamyPorównanie liczb całkowitych i ciągów na poziomie systemu

int a = 11; 
int b = 12; 

compare(a,b); //Just an example comparison, not in any particular language. 

And

String a = "11"; 
String b = "12"; 

compare(a,b); 

Teraz co pytam jest to, co jest różnica poziomu systemu pomiędzy tymi dwoma porównań? Pytanie nie dotyczy żadnego konkretnego języka, to tylko ogólny problem. Nie dotyczy to również konwersji/porównania z ciągiem do liczby całkowitej lub odwrotnie. Wiem, że odpowiedzi mogą być różne dla różnych platform i różnych języków, ale ponieważ nie mam o tym pojęcia, po prostu zadaję ogólne pytanie.

I dlaczego porównania całkowite są zawsze uważane za szybsze niż porównania ciągów znaków?

Odpowiedz

12

Zazwyczaj ciąg lub liczba całkowita (w najprostszej postaci) jest porównywany bajt po bajcie.

Tak dla int przykład, że staje się pojedyncza instrukcja CPU:

cmp a, b 

która biegnie dość szybko (przy założeniu 32-bitowych ints 32-bitowy procesor lub lepszy). To pojedyncze porównanie, które pasuje do rejestrów procesora.

Struny są jednak bardziej złożone. W najprostszym przypadku wygląda to następująco:

foreach (character c in string a, character d in string b) 
    cmp c, d 

i musi zapętlać cały ciąg, znak po znaku. Jeśli łańcuchy mają różną długość, musi sobie z tym poradzić (oczywiście oba są tego samego rozmiaru).

Na bardziej złożonym poziomie, z ustawieniami regionalnymi i różnymi zestawami znaków, każdy ciąg znaków może składać się z 2-4 bajtów, a niektóre znaki (z akcentami itp.) Mogą być porównywane jako równe sobie wzajemnie, mimo że mają różne wartości bajtów. W grę wchodzi znacznie więcej czynności i przetwarzanie, a więcej pracy prawie zawsze oznacza wolniejszy czas.

Dokładne zachowanie zależy od ustawień narodowych, zestawu znaków i języka. Niektóre języki (na przykład C#) przechowują łańcuchy o długości, podczas gdy inne (C) przechowują po prostu tablicę znaków. Inne języki mogą być zaprojektowane do przetwarzania ciągów lub mieć zoptymalizowane biblioteki do obsługi, co może obniżyć koszty.

Co ciekawe, teoretycznie, podczas pracy z ciągami ASCII porównywanie ciągów o długości do 3 znaków może być mniej więcej tak szybkie, jak porównanie intów. W takim przypadku ma to więcej wspólnego z ilością pamięci (AS2), która może wewnętrznie używać memcmp, co jest w przybliżeniu tym, co i tak będzie robił ==). Może to również dotyczyć języków, które przechowują długość łańcucha na początku i ciągi o długości 0 (puste), ponieważ mogą po prostu porównać długość (która może być int).

+0

Porównanie łańcuchów nie zawsze musi wyglądać na cały łańcuch; może zatrzymać się, gdy tylko znajdzie różnicę. – MRAB

+0

@peachykeen dzięki ostatni para był bardzo pomocny ... – buch11

+0

Dwie cyfry ciągu są przechowywane w 2 bajtach i całkowitą przechowywane w 4 bajtach (rozmawiają o programie C). Powiedziałeś, że porównanie wykonane bajt po bajcie niż porównanie łańcuchów zajmie tylko 2 porównania, a liczba całkowita zajmie 4. Czy to prawda? –

2

liczby całkowite są przechowywane jako wartości całkowitych reprezentowanych w formacie binarnym jako pojedynczy zestaw 1 i zer, zajmując kilka bajtów (w zależności od systemu operacyjnego)

struny są przechowywane jako jeden znak za cyfrą, każdy za pomocą wzoru bitowego w swoim bajcie.

Tak więc w twoim przykładzie ciągi zajmują około dwukrotnie większą ilość bajtów do reprezentacji w porównaniu z wzorcami.

+2

W języku C/C++ i wielu innych językach, int ma zwykle 4 bajty, a łańcuchy mogą mieć 1 bajt na znak, więc nawet z końcową wartością zerową łańcuchy mogą być mniejsze. Możliwe również z językiem, który używa długości jednej bajty i końcowej wartości null lub dwubajtowej i zerowej. Liczba bajtów na ciąg znaków również jest bardzo różna. – ssube

Powiązane problemy