Я попадаю в удивительную проблему.
Я загрузил текстовый файл в свое приложение, и у меня есть логика, которая сравнивает значение, имеющее µ.
И я понял, что даже если тексты одинаковые, значение сравнения ложное.
Console.WriteLine("μ".Equals("µ")); // returns false
Console.WriteLine("µ".Equals("µ")); // return true
В следующей строке копируется символ µ.
Однако это могут быть не единственные подобные персонажи.
Есть ли в C # способ сравнить символы, которые выглядят одинаково, но на самом деле разные?
Ответы:
Во многих случаях вы можете нормализовать оба символа Юникода до определенной формы нормализации, прежде чем сравнивать их, и они должны иметь возможность совпадать. Конечно, какая форма нормализации вам понадобится, зависит от самих персонажей; только потому , что они выглядят одинаково , не обязательно означает , что они представляют собой один и тот же характер. Вам также необходимо подумать, подходит ли это для вашего варианта использования - см. Комментарий Юкки К. Корпела.
В этой конкретной ситуации, если вы обратитесь к ссылкам в ответе Тони , вы увидите, что таблица для U + 00B5 говорит:
Это означает, что U + 00B5, второй символ в исходном сравнении, можно разложить на U + 03BC, первый символ.
Итак, вы нормализуете символы, используя полную декомпозицию совместимости, с формами нормализации KC или KD. Вот небольшой пример, который я написал, чтобы продемонстрировать:
Для получения дополнительной информации о нормализации Unicode и различных формах нормализации см
System.Text.NormalizationForm
и спецификация Unicode .источник
Поскольку это действительно разные символы, даже если они выглядят одинаково, первая - это настоящая буква и имеет char,
code = 956 (0x3BC)
а вторая - микрознак и имеет181 (0xB5)
.Ссылки:
Поэтому, если вы хотите сравнить их и вам нужно, чтобы они были равны, вам нужно обработать это вручную или заменить один символ другим перед сравнением. Или используйте следующий код:
И демо
источник
У них обоих разные коды символов: Подробнее см. Здесь.
Где 1-й:
источник
В конкретном примере
μ
(mu) иµ
(micro sign) последний имеет разложение совместимости с первым, поэтому вы можете нормализовать строкуFormKC
илиFormKD
преобразовать микрознаки в mus.Однако существует множество наборов символов, которые выглядят одинаково, но не эквивалентны ни в одной форме нормализации Unicode. Например,
A
(латиница),Α
(греческий) иА
(кириллица). На веб-сайте Unicode есть файл confusables.txt со списком, предназначенный для помощи разработчикам в защите от атак омографа . При необходимости вы можете проанализировать этот файл и построить таблицу для «визуальной нормализации» строк.источник
ToUpper
/ToLower
усложнит реализацию. Вы должны"B".ToLower()
бытьb
на английском, ноβ
на греческом ив
русском языках. Как бы то ни было, только турецкий (без точкиi
) и несколько других языков нуждаются в правилах регистра, отличных от установленных по умолчанию.Найдите оба символа в базе данных Unicode и увидите разницу .
Один из них - греческая строчная буква,
µ
а другой - микро-знакµ
.источник
ИЗМЕНИТЬ После слияния этого вопроса с Как сравнить «μ» и «µ» в C #
Исходный ответ опубликован:
РЕДАКТИРОВАТЬ После прочтения комментариев, да, использовать вышеуказанный метод нецелесообразно, потому что он может давать неправильные результаты для некоторых других типов входных данных, для этого мы должны использовать нормализацию с использованием полной декомпозиции совместимости, как указано в вики . (Благодаря ответу BoltClock )
Вывод
Читая информацию в Unicode_equivalence, я обнаружил
Таким образом, для сравнения эквивалентности мы обычно должны использовать
FormKC
нормализацию NFKC или нормализацию NFKDFormKD
.Мне было немного любопытно узнать больше обо всех символах Unicode, поэтому я сделал образец, который будет перебирать все символы Unicode,
UTF-16
и я получил некоторые результаты, которые хочу обсудить.FormC
иFormD
нормализованные значения не эквивалентныTotal: 12,118
Character (int value): 192-197, 199-207, 209-214, 217-221, 224-253, ..... 44032-55203
FormKC
иFormKD
нормализованные значения не эквивалентныTotal: 12,245
Character (int value): 192-197, 199-207, 209-214, 217-221, 224-228, ..... 44032-55203, 64420-64421, 64432-64433, 64490-64507, 64512-64516, 64612-64617, 64663-64667, 64735-64736, 65153-65164, 65269-65274
FormC
иFormD
нормализованные значения не были эквивалентны, тамFormKC
иFormKD
нормализованные значения также не были эквивалентными, за исключением следующихсимволов.
901 '΅', 8129 '῁', 8141 '῍', 8142 '῎', 8143 '῏', 8157 '῝', 8158 '῞'
, 8159 '῟', 8173 '῭', 8174 '΅'
FormKC
иFormKD
нормализованное значение не были эквивалентны, но тамFormC
иFormD
нормализованные значения были эквивалентнымиTotal: 119
Символы:
452 'DŽ' 453 'Dž' 454 'dž' 12814 '㈎' 12815 '㈏' 12816 '㈐' 12817 '㈑' 12818 '㈒' 12819 '㈓' 12820 '㈔' 12821 '㈕', 12822 '㈖' 12823 '㈗' 12824 '㈘' 12825 '㈙' 12826 '㈚' 12827 '㈛' 12828 '㈜' 12829 '㈝' 12830 '㈞' 12910 '㉮' 12911 '㉯' 12912 '㉰' 12913 '㉱' 12914 '㉲' 12915 '㉳' 12916 '㉴' 12917 '㉵' 12918 '㉶' 12919 '㉷' 12920 '㉸' 12921 '㉹' 12922 '㉺' 12923 '㉻' 12924 '㉼' 12925 '㉽' 12926 '㉾' 13056 '㌀' 13058 '㌂' 13060 '㌄' 13063 '㌇' 13070 '㌎' 13071 '㌏' 13072 '㌐' 13073 '㌑' 13075 '㌓' 13077 '㌕' 13080 '㌘' 13081 '㌙' 13082 '㌚' 13086 '㌞' 13089 '㌡' 13092 '㌤' 13093 '㌥' 13094 '㌦' 13099 '㌫' 13100 '㌬' 13101 '㌭' 13102 '㌮' 13103 '㌯' 13104 '㌰' 13105 '㌱' 13106 '㌲' 13108 '㌴' 13111 '㌷' 13112 '㌸' 13114 '㌺' 13115 '㌻' 13116 '㌼' 13117 '㌽' 13118 '㌾' 13120 '㍀' 13130 '㍊' 13131 '㍋' 13132 '㍌' 13134 '㍎' 13139 '㍓' 13140 '㍔' 13142 '㍖' .......... ﺋ' 65164 'ﺌ' 65269 'ﻵ' 65270 'ﻶ' 65271 'ﻷ' 65272 'ﻸ' 65273 'ﻹ' 65274'
ArgumentException
при попыткеTotal:2081
Characters(int value): 55296-57343, 64976-65007, 65534
Эти ссылки могут быть действительно полезны, чтобы понять, какие правила регулируют эквивалентность Unicode.
источник
"m".ToUpper().Equals("µ".ToUpper());
и"M".ToUpper().Equals("µ".ToUpper());
это тоже правда. Это может быть нежелательно.Скорее всего, есть два разных кода символа, которые делают (визуально) один и тот же символ. Хотя технически они не равны, они выглядят равными. Взгляните на таблицу символов и посмотрите, есть ли несколько экземпляров этого символа. Или распечатайте символьный код двух символов в вашем коде.
источник
Вы спрашиваете «как их сравнить», но не говорите нам, что хотите делать.
Есть как минимум два основных способа их сравнить:
Либо вы сравниваете их напрямую, как есть, а они разные
Или вы используете нормализацию совместимости Unicode, если вам нужно сравнение, которое обнаружит, что они совпадают.
Однако может возникнуть проблема, потому что нормализация совместимости Unicode заставит сравнивать многие другие символы. Если вы хотите, чтобы только эти два символа рассматривались как одинаковые, вам следует использовать собственные функции нормализации или сравнения.
Для более конкретного решения нам необходимо знать вашу конкретную проблему. В каком контексте вы столкнулись с этой проблемой?
источник
Если бы я хотел быть педантичным, я бы сказал, что ваш вопрос не имеет смысла, но поскольку мы приближаемся к Рождеству и птицы поют, я продолжу.
Во- первых, на 2 лица , которые вы пытаетесь сравнить это
glyph
с, глиф является частью набора символов , предоставляемых тем , что, как правило , знают , как «шрифт», то , что обычно приходит вttf
,otf
или любой другой формат файла , вы с помощью.Глифы представляют собой представление данного символа, и поскольку они представляют собой представление, которое зависит от определенного набора, вы не можете просто ожидать, что у вас будет 2 похожих или даже «лучших» идентичных символа, это фраза, которая не имеет смысла если вы учитываете контекст, вы должны, по крайней мере, указать, какой шрифт или набор глифов вы учитываете, когда формулируете подобный вопрос.
То, что обычно используется для решения проблемы, аналогичной той, с которой вы сталкиваетесь, - это OCR, по сути, программное обеспечение, которое распознает и сравнивает глифы. Если C # предоставляет OCR по умолчанию, я этого не знаю, но обычно это очень плохо идея, если вам действительно не нужно OCR, и вы знаете, что с ним делать.
Вы можете в конечном итоге интерпретировать книгу по физике как древнегреческую книгу, не упоминая о том, что OCR, как правило, является дорогостоящим с точки зрения ресурсов.
Есть причина, по которой эти символы локализованы так, как они локализованы, просто не делайте этого.
источник
Можно нарисовать оба символа с одинаковым стилем и размером шрифта с помощью
DrawString
метода. После создания двух растровых изображений с символами их можно сравнивать попиксельно.Преимущество этого метода в том, что можно сравнивать не только абсолютно одинаковые символы, но и похожие (с определенным допуском).
источник