2008-10-24 9 views
70

Если вы делаете сравнение без учета регистра, эффективнее ли преобразовать строку в верхний регистр или в нижний регистр? Это даже имеет значение?Верхний и нижний регистр

Предлагается in this SO post, что C# более эффективен с ToUpper, потому что «Microsoft оптимизировала его таким образом». Но я также прочитал this argument, что преобразование ToLower в сравнении с ToUpper зависит от того, что ваши строки содержат больше, и что обычно строки содержат более строчные символы, что делает ToLower более эффективным.

В частности, я хотел бы знать:

  • Есть ли способ оптимизировать ToUpper или ToLower таким образом, что один быстрее, чем другие?
  • Быстрее ли делать сравнение без учета регистра строк с верхним или нижним регистром и почему?
  • Существуют ли какие-либо среды программирования (например, C, C#, Python, что угодно), где один случай явно лучше, чем другой, и почему?

ответ

82

Преобразование в верхний регистр или в нижний регистр, чтобы исключить нечувствительность к регистру, неверно из-за «интересных» особенностей некоторых культур, особенно Турции. Вместо этого используйте StringComparer с соответствующими параметрами.

У MSDN есть great guidelines на обработку строк. Вы также можете проверить, что ваш код проходит the Turkey test.

РЕДАКТИРОВАТЬ: Комментарий Нейла около порядковый номер сравнение без учета регистра. Все это царство довольно мутное :(

-2

Если вы имеете дело с чистым ASCII, это не имеет значения. Это просто OR x, 32 против AND x, 224. Unicode, я понятия не имею ...

+4

Это совершенно неправильно - OR'ing с 32 работает только для A-Z и символов 64-127; он закручивает все остальные символы. И'инг с 32 еще более прав - результат всегда будет 0 (nul) или 32 (пробел). – 2008-10-24 18:34:25

12

Основываясь на строках, имеющих тенденцию иметь более строчные записи, ToLower теоретически должен быть быстрее (много сравнений, но немного назначений).

В C, или при использовании индивидуально доступных элементов каждой строки (например, строк C или типа строки в STL в C++), на самом деле это сравнение байт - такое сравнение UPPER ничем не отличается от lower.

Если вы были подлыми и загрузили свои строки в массивы long, вы бы получили очень быстрое сравнение по всей строке, поскольку оно могло сравнивать 4 байта за раз. Однако время загрузки может сделать его нецелесообразным.

Зачем вам нужно знать, что быстрее? Если вы не выполняете метрическую нагрузку сравнений, один, выполняющий пару циклов быстрее, не имеет отношения к скорости общего выполнения и звучит как преждевременная оптимизация :)

+10

Чтобы ответить на вопрос, почему мне нужно знать, что быстрее: мне не нужно знать, я просто хочу знать. :) Это просто случай, когда кто-то делает заявку (например, «сравнение строк в верхнем регистре быстрее!») И хочет знать, действительно ли это и/или почему они предъявили это требование. – Parappa 2008-10-24 18:06:35

+1

, что имеет смысл - я тоже очень любопытен в таких вещах :) – warren 2008-10-26 21:11:44

+0

С строками C, чтобы преобразовать `` s `и` t` в массивы longs, чтобы строки были равны, если массивы равны, вы должны пройдите вниз s и t, пока не найдете завершающий символ `` \ 0`` (иначе вы можете сравнить мусор за конец строк, что может быть незаконным доступом к памяти, вызывающим неопределенное поведение). Но тогда почему бы просто не проводить сравнения при ходьбе по персонажам один за другим? С C++-строками вы можете, вероятно, получить длину и `.c_str()`, наложить на `long *` и сравнить префикс length `.size() - .size()% (sizeof long)`. Выглядит немного подозрительно для меня, tho. – 2017-07-19 11:13:00

1

Это действительно не должно иметь значения. С символами ASCII это определенно не имеет значения - это всего лишь несколько сравнений и немного флип для любого направления. Unicode может быть немного более сложным, так как есть некоторые символы, которые меняют случай по странным путям, но там действительно не должно быть никакой разницы, если ваш текст не будет заполнен этими специальными символами.

17

По MSDN более эффективно передавать в строках и сказать сравнение игнорировать случай:

String.Compare (Стра, STRB, StringComparison.OrdinalIgnoreCase) эквивалентно (но быстрее чем) по телефону

String.Compare (ToUpperInvariant (strA), ToUpperInvariant (strB), StringComparison.Ordinal).

Эти сравнения все еще очень быстрые.

Конечно, если вы сравниваете одну строку снова и снова, это может не выполняться.

4

Если вы выполняете сравнение строк в C#, то значительно быстрее использовать .Equals() вместо преобразования обеих строк в верхний или нижний регистр. Еще один большой плюс для использования .Equals() заключается в том, что больше памяти не выделяется для двух новых строк верхнего и нижнего регистра.

+4

И в качестве бонуса, если вы выберете правильные варианты, он действительно даст вам правильные результаты :) – 2008-10-24 18:29:15

6

Microsoft оптимизировала ToUpperInvariant(), а не ToUpper(). Разница в том, что инвариант более дружелюбен к культуре. Если вам нужно делать нечувствительные к регистру сравнения строк, которые могут различаться в культуре, используйте Invariant, в противном случае эффективность инвариантного преобразования не должна иметь значения.

Я не могу сказать, работает ли ToUpper() или ToLower() быстрее. Я никогда не пробовал, так как у меня никогда не было ситуации, в которой производительность значила.

+0

, если Microsoft оптимизировала код для сравнения в верхнем регистре, потому что код ASCII для прописных букв содержит только две цифры 65 - 90, а ASCII код Строчные буквы 97 -122, который содержит 3 цифры (требуется больше обработки)? – 2016-12-20 09:47:01

0

Это зависит. Как указано выше, простой только ASCII, его идентичный. В .NET читайте и используйте String.Compare правильно для i18n (языки и юникод). Если вы знаете что-нибудь о вероятности ввода, используйте более распространенный случай.

Помните, что если вы выполняете несколько строк, то длина длины - отличный первый дискриминатор.

1

Выполнение этого права должно быть небольшим, незначительным преимуществом скорости, если вы переходите в нижний регистр, но это, как многие намекали, зависит от культуры и не наследует функцию но в строках преобразованный (много букв нижнего регистра означает несколько заданий в память) - преобразование в верхний регистр быстрее, если у вас есть строка с большим количеством заглавных букв

15

Из Microsoft на MSDN:

.

Best Practices for Using Strings in the .NET Framework

Рекомендации String Применение

Почему? От Microsoft:

Нормализация строки в верхний регистр

Существует небольшая группа символов, которые при преобразовании в нижний регистр не может сделать путешествие туда и обратно.

Что такое пример такого персонажа, который не может совершить кругосветное путешествие?

  • Начало: Греческий Rho Символ (U + 03f1) & # x03f1;
  • Прописной: Капитал Греческий Rho (U + 03a1) & # x03a1;
  • Нижняя регистр: Малый греческий Rho (U + 03c1) & # x03c1;

& # x03f1; , & # x03a1;, & # x03c1;

Вот почему, если вы хотите делать нечувствительные к регистру сравнения, вы конвертируете строки в верхний регистр, а не в нижний регистр.

Смежные вопросы