Caigo en un tema sorprendente.
Cargué un archivo de texto en mi aplicación y tengo algo de lógica que compara el valor con µ.
Y me di cuenta de que incluso si los textos son los mismos, el valor de comparación es falso.
Console.WriteLine("μ".Equals("µ")); // returns false
Console.WriteLine("µ".Equals("µ")); // return true
En la línea posterior se copia el carácter µ.
Sin embargo, es posible que estos no sean los únicos personajes que sean así.
¿Hay alguna forma en C # de comparar los caracteres que se ven iguales pero en realidad son diferentes?
Respuestas:
En muchos casos, puede normalizar ambos caracteres Unicode a una determinada forma de normalización antes de compararlos, y deberían poder coincidir. Por supuesto, la forma de normalización que debe utilizar depende de los propios personajes; el hecho de que se parezcan no significa necesariamente que representen el mismo personaje. También debe considerar si es apropiado para su caso de uso; consulte el comentario de Jukka K. Korpela.
Para esta situación particular, si consulta los enlaces en la respuesta de Tony , verá que la tabla para U + 00B5 dice:
Esto significa que U + 00B5, el segundo carácter en su comparación original, se puede descomponer en U + 03BC, el primer carácter.
Por lo tanto, normalizará los caracteres mediante la descomposición de compatibilidad total, con las formas de normalización KC o KD. Aquí hay un ejemplo rápido que escribí para demostrar:
Para obtener detalles sobre la normalización Unicode y las diferentes formas de normalización, consulte
System.Text.NormalizationForm
y la especificación Unicode .fuente
Debido a que son símbolos realmente diferentes, incluso si se ven iguales, el primero es la letra real y tiene char
code = 956 (0x3BC)
y el segundo es el micro signo y tiene181 (0xB5)
.Referencias:
Entonces, si desea compararlos y necesita que sean iguales, debe manejarlo manualmente o reemplazar un carácter por otro antes de la comparación. O use el siguiente código:
Y la demo
fuente
Ambos tienen códigos de caracteres diferentes: consulte esto para obtener más detalles
Donde, el primero es:
fuente
Para el ejemplo específico de
μ
(mu) yµ
(micro signo), el último tiene una descomposición de compatibilidad con el primero, por lo que puede normalizar la cadenaFormKC
aoFormKD
convertir los micro signos en mus.Sin embargo, hay muchos conjuntos de caracteres que se parecen pero no son equivalentes en ninguna forma de normalización Unicode. Por ejemplo,
A
(latín),Α
(griego) yА
(cirílico). El sitio web Unicode tiene un archivo confusables.txt con una lista de estos, destinado a ayudar a los desarrolladores a protegerse contra los ataques homógrafos . Si es necesario, puede analizar este archivo y crear una tabla para la "normalización visual" de cadenas.fuente
ToUpper
/ToLower
difícil de implementar. Debería"B".ToLower()
estarb
en inglés, peroβ
en griego yв
en ruso. Tal como está, solo el turco (sin puntosi
) y un par de otros idiomas necesitan reglas de mayúsculas y minúsculas diferentes de las predeterminadas.Busque ambos caracteres en una base de datos Unicode y vea la diferencia .
Una es la letra minúscula griega
µ
y la otra es el micro signoµ
.fuente
EDITAR Después de la fusión de esta pregunta con Cómo comparar 'μ' y 'µ' en C #
Respuesta original publicada:
EDITAR Después de leer los comentarios, sí, no es bueno usar el método anterior porque puede proporcionar resultados incorrectos para algún otro tipo de entradas, para esto debemos usar normalizar usando la descomposición de compatibilidad completa como se menciona en wiki . (Gracias a la respuesta publicada por BoltClock )
Salida
Mientras leía información en Unicode_equivalence encontré
Por tanto, para comparar la equivalencia deberíamos utilizar normalmente, por
FormKC
ejemplo, la normalización NFKC o, porFormKD
ejemplo, la normalización NFKD.Tenía un poco de curiosidad por saber más sobre todos los caracteres Unicode, así que hice una muestra que iteraría sobre todo el carácter Unicode
UTF-16
y obtuve algunos resultados que quiero discutirFormC
yFormD
no eran equivalentesTotal: 12,118
Character (int value): 192-197, 199-207, 209-214, 217-221, 224-253, ..... 44032-55203
FormKC
yFormKD
no eran equivalentesTotal: 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
yFormD
no eran equivalentes, allíFormKC
y losFormKD
valores normalizados tampoco eran equivalentes excepto estos caracteresCaracteres:
901 '΅', 8129 '῁', 8141 '῍', 8142 '῎', 8143 '῏', 8157 '῝', 8158 '῞'
, 8159 '῟', 8173 '῭', 8174 '΅'
FormKC
yFormKD
valor normalizado no eran equivalentes, peroFormC
yFormD
valores normalizados fueron equivalentesTotal: 119
Caracteres:
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
si se intentaTotal:2081
Characters(int value): 55296-57343, 64976-65007, 65534
Estos enlaces pueden ser realmente útiles para comprender qué reglas rigen para la equivalencia Unicode
fuente
"m".ToUpper().Equals("µ".ToUpper());
y"M".ToUpper().Equals("µ".ToUpper());
también es cierto. Esto puede no ser deseable.Lo más probable es que haya dos códigos de caracteres diferentes que hacen (visiblemente) el mismo carácter. Aunque técnicamente no son iguales, se ven iguales. Eche un vistazo a la tabla de personajes y vea si hay varias instancias de ese personaje. O imprima el código de carácter de los dos caracteres en su código.
fuente
Pregunta "cómo compararlos" pero no nos dice qué quiere hacer.
Hay al menos dos formas principales de compararlos:
O los comparas directamente como eres y son diferentes
O usa la Normalización de compatibilidad Unicode si lo que necesita es una comparación que los encuentre para coincidir.
Sin embargo, podría haber un problema porque la normalización de la compatibilidad Unicode hará que muchos otros caracteres se comparen igual. Si desea que solo estos dos caracteres sean tratados como iguales, debe lanzar sus propias funciones de normalización o comparación.
Para una solución más específica, necesitamos conocer su problema específico. ¿En qué contexto se encontró con este problema?
fuente
Si quisiera ser pedante, diría que su pregunta no tiene sentido, pero como nos acercamos a la Navidad y los pájaros cantan, continuaré con esto.
En primer lugar, las 2 entidades que intentas comparar son
glyph
s, un glifo es parte de un conjunto de glifos proporcionado por lo que generalmente se conoce como "fuente", lo que generalmente viene en unttf
,otf
o cualquier formato de archivo que tenga utilizando.Los glifos son una representación de un símbolo dado y, dado que son una representación que depende de un conjunto específico, no puede esperar tener 2 símbolos idénticos similares o incluso "mejores", es una frase que no tiene sentido si considera el contexto, al menos debe especificar qué fuente o conjunto de glifos está considerando cuando formula una pregunta como esta.
Lo que generalmente se usa para resolver un problema similar al que está encontrando, es un OCR, esencialmente un software que reconoce y compara glifos. Si C # proporciona un OCR de forma predeterminada, no lo sé, pero generalmente es muy malo. idea si realmente no necesita un OCR y sabe qué hacer con él.
Es posible que termine interpretando un libro de física como un libro griego antiguo sin mencionar el hecho de que los OCR son generalmente costosos en términos de recursos.
Hay una razón por la cual esos caracteres están localizados de la forma en que están localizados, simplemente no hagas eso.
fuente
Es posible dibujar ambos caracteres con el mismo estilo y tamaño de fuente con
DrawString
método. Una vez generados dos mapas de bits con símbolos, es posible compararlos píxel por píxel.La ventaja de este método es que puede comparar no solo caracteres absolutamente iguales, sino también similares (con tolerancia definida).
fuente