จะเปรียบเทียบอักขระ Unicode ที่“ เหมือนกัน” ได้อย่างไร?


94

ฉันตกอยู่ในปัญหาที่น่าประหลาดใจ

ฉันโหลดไฟล์ข้อความในแอปพลิเคชันของฉันและฉันมีตรรกะบางอย่างที่เปรียบเทียบค่าที่มี µ

และฉันก็ตระหนักว่าแม้ว่าข้อความจะเหมือนกัน แต่ค่าเปรียบเทียบจะเป็นเท็จ

 Console.WriteLine("μ".Equals("µ")); // returns false
 Console.WriteLine("µ".Equals("µ")); // return true

ในบรรทัดต่อมาจะมีการคัดลอกอักขระ µ มาวาง

อย่างไรก็ตามสิ่งเหล่านี้อาจไม่ใช่ตัวละครเดียวที่เป็นเช่นนี้

มีวิธีใดใน C # ในการเปรียบเทียบตัวอักษรที่มีลักษณะเหมือนกัน แต่แตกต่างกันจริงหรือไม่?


159
ดูเหมือนว่าคุณจะพบมูของSchrödinger
BoltClock

19
อักขระต่างกันแม้ว่าจะมีลักษณะเหมือนกัน แต่ก็มีรหัสอักขระที่แตกต่างกัน
user2864740

94
ยินดีต้อนรับสู่ Unicode
ta.speot.is

11
คุณต้องการบรรลุอะไร สองคนนั้นควรจะเท่ากันแล้วแม้กระทั่งรหัสตัวอักษรของพวกเขาก็แตกต่างกัน แต่หน้าเหมือนกัน?
Jade

28
“ ดูเหมือนกัน” และ“ เหมือนกัน” เป็นแนวคิดที่คลุมเครือ พวกเขาหมายถึงเอกลักษณ์ของร่ายมนตร์หรือเพียงแค่ความคล้ายคลึงกัน? ใกล้แค่ไหน? โปรดทราบว่าอักขระสองตัวอาจมีร่ายมนตร์ที่เหมือนกันในบางฟอนต์คล้ายกันมากในฟอนต์อื่นและค่อนข้างแตกต่างกันในฟอนต์อื่น สิ่งที่สำคัญคือเหตุใดคุณจึงทำการเปรียบเทียบเช่นนั้นและในบริบทใด (และการยอมรับผลบวกเท็จและผลลบเท็จ)
Jukka K. Korpela

คำตอบ:


125

ในหลาย ๆ กรณีคุณสามารถทำให้อักขระ Unicode ทั้งสองเป็นรูปแบบการทำให้เป็นมาตรฐานเดียวกันก่อนที่จะเปรียบเทียบกันและควรจะจับคู่กันได้ แน่นอนว่ารูปแบบการปรับมาตรฐานที่คุณต้องใช้นั้นขึ้นอยู่กับตัวละครนั้น ๆ เพียงเพราะพวกเขาดูเหมือนกันไม่จำเป็นต้องหมายความว่าพวกเขาแสดงถึงตัวละครเดียวกัน คุณต้องพิจารณาด้วยว่าเหมาะสมกับกรณีการใช้งานของคุณหรือไม่ - ดูความคิดเห็นของ Jukka K. Korpela

สำหรับสถานการณ์เฉพาะนี้หากคุณอ้างถึงลิงก์ในคำตอบของ Tonyคุณจะเห็นว่าตารางสำหรับU + 00B5ระบุว่า:

การสลายตัว <compat> กรีกตัวอักษรขนาดเล็ก MU (U + 03BC)

ซึ่งหมายความว่า U + 00B5 ซึ่งเป็นอักขระตัวที่สองในการเปรียบเทียบดั้งเดิมของคุณสามารถแยกย่อยเป็น U + 03BC ซึ่งเป็นอักขระตัวแรก

ดังนั้นคุณจะทำให้อักขระเป็นปกติโดยใช้การสลายความเข้ากันได้เต็มรูปแบบโดยใช้รูปแบบการทำให้เป็นมาตรฐาน KC หรือ KD นี่คือตัวอย่างสั้น ๆ ที่ฉันเขียนขึ้นเพื่อสาธิต:

using System;
using System.Text;

class Program
{
    static void Main(string[] args)
    {
        char first = 'μ';
        char second = 'µ';

        // Technically you only need to normalize U+00B5 to obtain U+03BC, but
        // if you're unsure which character is which, you can safely normalize both
        string firstNormalized = first.ToString().Normalize(NormalizationForm.FormKD);
        string secondNormalized = second.ToString().Normalize(NormalizationForm.FormKD);

        Console.WriteLine(first.Equals(second));                     // False
        Console.WriteLine(firstNormalized.Equals(secondNormalized)); // True
    }
}

สำหรับรายละเอียดเกี่ยวกับ Unicode ฟื้นฟูและรูปแบบที่แตกต่างกันฟื้นฟูอ้างถึงSystem.Text.NormalizationFormและข้อมูลจำเพาะ Unicode


26
ขอบคุณสำหรับลิงค์ข้อมูลจำเพาะของ Unicode ครั้งแรกที่ฉันอ่านมัน หมายเหตุเล็ก ๆ จากนั้น: "ต้องไม่ใช้แบบฟอร์ม Normalization KC และ KD แบบสุ่มสี่สุ่มห้ากับข้อความตามอำเภอใจ .. ที่ดีที่สุดคือคิดว่าแบบฟอร์ม Normalization เหล่านี้เป็นเหมือนการแมปตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็ก: มีประโยชน์ในบางบริบทในการระบุความหมายหลัก แต่ยังมีประโยชน์ การแก้ไขข้อความที่อาจไม่เหมาะสมเสมอไป "
user2864740

149

เพราะมันเป็นสัญลักษณ์ที่แตกต่างกันจริงๆแม้พวกเขามีลักษณะเดียวกันเป็นครั้งแรกคืออักษรที่เกิดขึ้นจริงและมีถ่านและสองคือเครื่องหมายจุลภาคและมีcode = 956 (0x3BC)181 (0xB5)

อ้างอิง:

ดังนั้นหากคุณต้องการเปรียบเทียบและคุณต้องการให้มันเท่ากันคุณต้องจัดการด้วยตนเองหรือแทนที่หนึ่งถ่านก่อนที่จะเปรียบเทียบ หรือใช้รหัสต่อไปนี้:

public void Main()
{
    var s1 = "μ";
    var s2 = "µ";

    Console.WriteLine(s1.Equals(s2));  // false
    Console.WriteLine(RemoveDiacritics(s1).Equals(RemoveDiacritics(s2))); // true 
}

static string RemoveDiacritics(string text) 
{
    var normalizedString = text.Normalize(NormalizationForm.FormKC);
    var stringBuilder = new StringBuilder();

    foreach (var c in normalizedString)
    {
        var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
        if (unicodeCategory != UnicodeCategory.NonSpacingMark)
        {
            stringBuilder.Append(c);
        }
    }

    return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}

และการสาธิต


11
ด้วยความอยากรู้อยากเห็นเหตุผลที่มีสัญลักษณ์ µ สองตัวคืออะไร? คุณไม่เห็น K เฉพาะที่มีชื่อ "Kilo sign" (หรือคุณ?)
MartinHaTh

12
@MartinHaTh: ตามที่วิกิพีเดียมัน"ด้วยเหตุผลทางประวัติศาสตร์"
BoltClock

12
Unicode มีอักขระที่เข้ากันได้จำนวนมากที่นำมาจากชุดอักขระรุ่นเก่า (เช่นISO 8859-1 ) เพื่อให้การแปลงจากชุดอักขระเหล่านั้นง่ายขึ้น ย้อนกลับไปเมื่อชุดอักขระถูก จำกัด ไว้ที่ 8 บิตพวกเขาจะรวมร่ายมนตร์สองสามตัว (เช่นอักษรกรีกบางตัว) สำหรับการใช้ทางคณิตศาสตร์และวิทยาศาสตร์ทั่วไป การใช้สัญลักษณ์ซ้ำตามรูปลักษณ์เป็นเรื่องปกติดังนั้นจึงไม่มีการเพิ่ม 'K' แบบพิเศษ แต่มันก็เป็นวิธีแก้ปัญหาเสมอ สัญลักษณ์ที่ถูกต้องสำหรับ "micro" คือ mu ตัวพิมพ์เล็กที่แท้จริงของกรีกสัญลักษณ์ที่ถูกต้องสำหรับ Ohm คือโอเมก้าตัวพิมพ์ใหญ่และอื่น ๆ
VGR

8
ไม่มีอะไรดีไปกว่าเมื่อมีบางอย่างทำเพื่อลูกเกดที่ตีโพยตีพาย
Paulm

11
มี K พิเศษสำหรับธัญพืชหรือไม่?

86

ทั้งสองมีรหัสอักขระที่แตกต่างกันโปรดดูรายละเอียดเพิ่มเติม

Console.WriteLine((int)'μ');  //956
Console.WriteLine((int)'µ');  //181

โดยที่ 1 คือ:

Display     Friendly Code   Decimal Code    Hex Code    Description
====================================================================
μ           &mu;            &#956;          &#x3BC;     Lowercase Mu
µ           &micro;         &#181;          &#xB5;      micro sign Mu

ภาพ


39

สำหรับตัวอย่างเฉพาะของμ(mu) และµ(เครื่องหมายไมโคร) ตัวหลังมีการสลายตัวที่เข้ากันได้กับอดีตดังนั้นคุณสามารถทำให้สตริงเป็นปกติFormKCหรือFormKDแปลงสัญญาณไมโครเป็นมัสได้

อย่างไรก็ตามมีชุดอักขระมากมายที่มีลักษณะเหมือนกัน แต่ไม่เทียบเท่าภายใต้รูปแบบการปรับมาตรฐาน Unicode ใด ๆ ตัวอย่างเช่นA(ละติน) Α(กรีก) และА(ซีริลลิก) เว็บไซต์ Unicode มีconfusables.txtไฟล์ที่มีรายชื่อของเหล่านี้มีจุดมุ่งหมายเพื่อพัฒนาความช่วยเหลือป้องกันการโจมตีคำพ้องรูป หากจำเป็นคุณสามารถแยกวิเคราะห์ไฟล์นี้และสร้างตารางสำหรับ "การทำให้เป็นภาพปกติ" ของสตริง


สิ่งที่ดีที่ควรทราบเมื่อใช้ Normalize ดูเหมือนน่าแปลกใจที่พวกเขายังคงแตกต่างกัน
user2864740

4
@ user2864740: ถ้าตัวพิมพ์ใหญ่ภาษากรีก tau ไม่แตกต่างจากตัวอักษรโรมัน T มันจะเป็นเรื่องยากมากที่จะจัดเรียงข้อความภาษากรีกและโรมันตามลำดับตัวอักษรอย่างสมเหตุสมผล นอกจากนี้หากแบบอักษรต้องใช้รูปแบบการมองเห็นที่แตกต่างกันสำหรับอักษรกรีกและโรมันจะเป็นการรบกวนอย่างมากหากตัวอักษรกรีกที่มีรูปร่างคล้ายตัวอักษรโรมันแสดงผลแตกต่างจากที่ไม่มี
supercat

7
ที่สำคัญกว่านั้นการรวมตัวอักษรของยุโรปจะทำให้ToUpper/ ToLowerนำไปใช้ได้ยาก คุณต้อง"B".ToLower()เป็นbภาษาอังกฤษ แต่เป็นβภาษากรีกและвภาษารัสเซีย ตามที่เป็นอยู่มีเพียงภาษาตุรกี (ไม่มีจุดi) และภาษาอื่น ๆ อีกสองภาษาเท่านั้นที่ต้องการกฎการใช้ตัวพิมพ์ที่แตกต่างจากค่าเริ่มต้น
dan04

@ dan04: ฉันสงสัยว่ามีใครเคยคิดที่จะกำหนดจุดรหัสเฉพาะให้กับ "i" และ "I" ของตุรกีทั้งสี่รูปแบบหรือไม่ นั่นจะช่วยขจัดความคลุมเครือในพฤติกรรมของ toUpper / toLower
supercat

34

ค้นหาตัวละครทั้งสองในฐานข้อมูล Unicodeและเห็นความแตกต่าง

หนึ่งคืออักษรตัวเล็กกรีก µและอื่น ๆ ที่เป็นMicro µเข้าสู่ระบบ

Name            : MICRO SIGN
Block           : Latin-1 Supplement
Category        : Letter, Lowercase [Ll]
Combine         : 0
BIDI            : Left-to-Right [L]
Decomposition   : <compat> GREEK SMALL LETTER MU (U+03BC)
Mirror          : N
Index entries   : MICRO SIGN
Upper case      : U+039C
Title case      : U+039C
Version         : Unicode 1.1.0 (June, 1993)

Name            : GREEK SMALL LETTER MU
Block           : Greek and Coptic
Category        : Letter, Lowercase [Ll]
Combine         : 0
BIDI            : Left-to-Right [L]
Mirror          : N
Upper case      : U+039C
Title case      : U+039C
See Also        : micro sign U+00B5
Version         : Unicode 1.1.0 (June, 1993)

4
สิ่งนี้ได้รับ 37 upvotes อย่างไร? มันไม่ตอบคำถาม ("วิธีเปรียบเทียบอักขระ Unicode") เพียงแค่แสดงความคิดเห็นว่าเหตุใดตัวอย่างนี้จึงไม่เท่ากัน อย่างดีที่สุดควรเป็นความคิดเห็นเกี่ยวกับคำถาม ฉันเข้าใจว่าตัวเลือกการจัดรูปแบบความคิดเห็นไม่อนุญาตให้โพสต์ได้ดีเท่ากับตัวเลือกการจัดรูปแบบคำตอบ แต่นั่นไม่ควรเป็นเหตุผลที่ถูกต้องในการโพสต์เป็นคำตอบ
Konerak

5
จริงๆแล้วคำถามก็คนละคำถามถามว่าทำไมการตรวจสอบความเท่าเทียมกันของμและ µ จึงส่งคืนเท็จ คำตอบนี้ตอบโจทย์ ต่อมา OP ถามคำถามอื่น (คำถามนี้) ว่าจะเปรียบเทียบอักขระสองตัวที่มีลักษณะเหมือนกันได้อย่างไร คำถามทั้งสองมีคำตอบที่ดีที่สุดและต่อมาหนึ่งในผู้ดูแลได้รวมคำถามทั้งสองโดยเลือกคำตอบที่ดีที่สุดของคำถามที่สองให้ดีที่สุด มีคนแก้ไขคำถามนี้เพื่อที่จะสรุป
Subin Jacob

อันที่จริงฉันไม่ได้เพิ่มเนื้อหาใด ๆ หลังจากการรวม
Subin Jacob

24

แก้ไขหลังจากการรวมคำถามนี้กับวิธีเปรียบเทียบ 'μ' และ 'µ' ใน C #
คำตอบเดิมที่โพสต์:

 "μ".ToUpper().Equals("µ".ToUpper()); //This always return true.

แก้ไข หลังจากที่ได้อ่านความคิดเห็นที่ใช่มันไม่ดีที่จะใช้วิธีการดังกล่าวข้างต้นเพราะมันอาจให้ผลลัพธ์ที่ไม่ถูกต้องสำหรับประเภทอื่น ๆ บางส่วนของปัจจัยการผลิตสำหรับวันนี้เราควรใช้ปกติโดยใช้การสลายตัวเข้ากันได้เต็มรูปแบบตามที่กล่าวไว้ในวิกิพีเดีย (ขอบคุณคำตอบที่โพสต์โดยBoltClock )

    static string GREEK_SMALL_LETTER_MU = new String(new char[] { '\u03BC' });
    static string MICRO_SIGN = new String(new char[] { '\u00B5' });

    public static void Main()
    {
        string Mus = "µμ";
        string NormalizedString = null;
        int i = 0;
        do
        {
            string OriginalUnicodeString = Mus[i].ToString();
            if (OriginalUnicodeString.Equals(GREEK_SMALL_LETTER_MU))
                Console.WriteLine(" INFORMATIO ABOUT GREEK_SMALL_LETTER_MU");
            else if (OriginalUnicodeString.Equals(MICRO_SIGN))
                Console.WriteLine(" INFORMATIO ABOUT MICRO_SIGN");

            Console.WriteLine();
            ShowHexaDecimal(OriginalUnicodeString);                
            Console.WriteLine("Unicode character category " + CharUnicodeInfo.GetUnicodeCategory(Mus[i]));

            NormalizedString = OriginalUnicodeString.Normalize(NormalizationForm.FormC);
            Console.Write("Form C Normalized: ");
            ShowHexaDecimal(NormalizedString);               

            NormalizedString = OriginalUnicodeString.Normalize(NormalizationForm.FormD);
            Console.Write("Form D Normalized: ");
            ShowHexaDecimal(NormalizedString);               

            NormalizedString = OriginalUnicodeString.Normalize(NormalizationForm.FormKC);
            Console.Write("Form KC Normalized: ");
            ShowHexaDecimal(NormalizedString);                

            NormalizedString = OriginalUnicodeString.Normalize(NormalizationForm.FormKD);
            Console.Write("Form KD Normalized: ");
            ShowHexaDecimal(NormalizedString);                
            Console.WriteLine("_______________________________________________________________");
            i++;
        } while (i < 2);
        Console.ReadLine();
    }

    private static void ShowHexaDecimal(string UnicodeString)
    {
        Console.Write("Hexa-Decimal Characters of " + UnicodeString + "  are ");
        foreach (short x in UnicodeString.ToCharArray())
        {
            Console.Write("{0:X4} ", x);
        }
        Console.WriteLine();
    }

เอาต์พุต

INFORMATIO ABOUT MICRO_SIGN    
Hexa-Decimal Characters of µ  are 00B5
Unicode character category LowercaseLetter
Form C Normalized: Hexa-Decimal Characters of µ  are 00B5
Form D Normalized: Hexa-Decimal Characters of µ  are 00B5
Form KC Normalized: Hexa-Decimal Characters of µ  are 03BC
Form KD Normalized: Hexa-Decimal Characters of µ  are 03BC
 ________________________________________________________________
 INFORMATIO ABOUT GREEK_SMALL_LETTER_MU    
Hexa-Decimal Characters of µ  are 03BC
Unicode character category LowercaseLetter
Form C Normalized: Hexa-Decimal Characters of µ  are 03BC
Form D Normalized: Hexa-Decimal Characters of µ  are 03BC
Form KC Normalized: Hexa-Decimal Characters of µ  are 03BC
Form KD Normalized: Hexa-Decimal Characters of µ  are 03BC
 ________________________________________________________________

ขณะอ่านข้อมูลในUnicode_equivalenceฉันพบ

การเลือกเกณฑ์การเทียบเท่าอาจส่งผลต่อผลการค้นหา ตัวอย่างเช่นอักษรควบการพิมพ์บางอย่างเช่น U + FB03 (ffi) ..... ดังนั้นการค้นหา U + 0066 (f) เนื่องจากสตริงย่อยจะประสบความสำเร็จในการปรับมาตรฐานNFKCของ U + FB03 แต่ไม่อยู่ในการปรับมาตรฐานNFCของ U + FB03

ดังนั้นเพื่อเปรียบเทียบความเท่าเทียมกันโดยปกติเราควรใช้FormKCเช่น NFKC normalization หรือFormKDเช่น NFKD normalization
ฉันไม่ค่อยอยากรู้ข้อมูลเพิ่มเติมเกี่ยวกับอักขระ 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

  1. Unicode_equivalence
  2. Unicode_compatibility_characters

4
แปลก แต่ใช้งานได้ ... ฉันหมายความว่ามันเป็นสองตัวอักษรที่แตกต่างกันที่มีความหมายต่างกันและการแปลงเป็นตัวบนทำให้เท่ากัน? ฉันไม่เห็นตรรกะ แต่เป็นทางออกที่ดี +1
BudBrot

45
โซลูชันนี้ปกปิดปัญหาและอาจทำให้เกิดปัญหาในกรณีทั่วไป การเรียงลำดับของการทดสอบนี้จะพบว่า"m".ToUpper().Equals("µ".ToUpper());และ"M".ToUpper().Equals("µ".ToUpper());นอกจากนี้ยังมีความจริง สิ่งนี้อาจไม่เป็นที่ต้องการ
Andrew Leach

6
-1 - นี่เป็นความคิดที่แย่มาก อย่าทำงานกับ Unicode เช่นนี้
Konrad Rudolph

1
แทนที่จะใช้เทคนิค ToUpper () ทำไมไม่ใช้ String.Equals ("μ", "μ", StringComparison.CurrentCultureIgnoreCase)
svenv

6
มีเหตุผลที่ดีอย่างหนึ่งในการแยกความแตกต่างระหว่าง "MICRO SIGN" และ "GREEK SMALL LETTER MU" นั่นคือการบอกว่า "ตัวพิมพ์ใหญ่" ของเครื่องหมายไมโครยังคงเป็นเครื่องหมายไมโคร แต่การใช้อักษรตัวพิมพ์ใหญ่เปลี่ยนไมโครเป็นเมกะวิศวกรรมที่มีความสุข
Greg

9

เป็นไปได้มากว่ามีรหัสอักขระสองตัวที่แตกต่างกันซึ่งทำให้ (เห็นได้ชัด) เป็นอักขระเดียวกัน แม้ว่าในทางเทคนิคจะไม่เท่ากัน แต่ก็ดูเท่าเทียมกัน ดูตารางอักขระและดูว่ามีหลายอินสแตนซ์ของอักขระนั้นหรือไม่ หรือพิมพ์รหัสอักขระของอักขระสองตัวในรหัสของคุณ


6

คุณถามว่า "จะเปรียบเทียบอย่างไร" แต่คุณไม่ได้บอกเราว่าคุณต้องการทำอะไร

มีอย่างน้อยสองวิธีหลักในการเปรียบเทียบ:

ไม่ว่าคุณจะเปรียบเทียบโดยตรงกับคุณและพวกเขาก็แตกต่างกัน

หรือคุณใช้ Unicode Compatibility Normalization หากคุณต้องการการเปรียบเทียบที่พบว่าตรงกัน

อาจมีปัญหาได้เนื่องจากการปรับมาตรฐานความเข้ากันได้ของ Unicode จะทำให้อักขระอื่น ๆ จำนวนมากเปรียบเทียบเท่ากัน หากคุณต้องการให้เฉพาะอักขระสองตัวนี้ได้รับการปฏิบัติเหมือนกันคุณควรหมุนฟังก์ชันการปรับมาตรฐานหรือการเปรียบเทียบของคุณเอง

สำหรับวิธีการแก้ปัญหาที่เฉพาะเจาะจงมากขึ้นเราจำเป็นต้องทราบปัญหาเฉพาะของคุณ บริบทที่คุณพบปัญหานี้คืออะไร?


1
"เครื่องหมายจุลภาค" และอักขระ mu ตัวพิมพ์เล็กเทียบเท่าตามรูปแบบบัญญัติหรือไม่ การใช้การปรับมาตรฐานตามรูปแบบบัญญัติจะทำให้คุณได้รับการเปรียบเทียบที่เข้มงวดมากขึ้น
Tanner Swett

@ TannerL.Swett: อันที่จริงฉันไม่แน่ใจด้วยซ้ำว่าจะตรวจสอบสิ่งนั้นอย่างไรจากด้านบนของหัว ...
hippietrail

1
อันที่จริงฉันกำลังนำเข้าไฟล์ที่มีสูตรฟิสิกส์ คุณพูดถูกเกี่ยวกับการทำให้เป็นมาตรฐาน ต้องผ่านมันให้ลึกกว่านี้ ..
DJ

ไฟล์แบบไหน? สิ่งที่ทำด้วยมือเป็นข้อความ Unicode ธรรมดาโดยบุคคลหรือไม่? หรือบางสิ่งที่แอปออกมาในรูปแบบเฉพาะ?
hippietrail

5

ถ้าฉันอยากจะอวดดีฉันจะบอกว่าคำถามของคุณไม่สมเหตุสมผล แต่เนื่องจากเราใกล้คริสต์มาสและนกกำลังร้องเพลงฉันจะดำเนินการต่อไป

ปิดแรกให้ 2 หน่วยงานที่คุณกำลังพยายามที่จะเปรียบเทียบglyphS, A สัญลักษณ์เป็นส่วนหนึ่งของชุดของร่ายมนตร์ให้โดยสิ่งที่มักจะรู้ว่าเป็น "ตัวอักษร" สิ่งที่มักจะมาในttf, otfหรือไฟล์รูปแบบใดก็ตามที่คุณอยู่ โดยใช้.

ร่ายมนตร์เป็นการแสดงสัญลักษณ์ที่กำหนดและเนื่องจากเป็นสัญลักษณ์ที่ขึ้นอยู่กับชุดเฉพาะคุณจึงไม่สามารถคาดหวังได้ว่าจะมีสัญลักษณ์ที่เหมือนกัน 2 ตัวหรือ "ดีกว่า" จึงเป็นวลีที่ไม่สมเหตุสมผล หากคุณพิจารณาบริบทอย่างน้อยคุณควรระบุแบบอักษรหรือชุดของร่ายมนตร์ที่คุณกำลังพิจารณาเมื่อตั้งคำถามเช่นนี้

สิ่งที่มักจะใช้ในการแก้ปัญหาที่คล้ายกับที่คุณพบคือ OCR ซึ่งโดยพื้นฐานแล้วเป็นซอฟต์แวร์ที่จดจำและเปรียบเทียบร่ายมนตร์ถ้า C # ให้OCRโดยค่าเริ่มต้นฉันไม่รู้ แต่โดยทั่วไปแล้วมันแย่มาก แนวคิดถ้าคุณไม่ต้องการ OCR จริงๆและคุณรู้ว่าจะทำอย่างไรกับมัน

คุณสามารถตีความหนังสือฟิสิกส์เป็นหนังสือกรีกโบราณได้โดยไม่ต้องพูดถึงข้อเท็จจริงที่ว่า OCR โดยทั่วไปมีราคาแพงในแง่ของทรัพยากร

มีเหตุผลว่าทำไมอักขระเหล่านั้นจึงได้รับการแปลเป็นภาษาท้องถิ่นเพียงแค่ไม่ทำเช่นนั้น


1

เป็นไปได้ที่จะวาดทั้งสองตัวอักษรที่มีรูปแบบและขนาดตัวอักษรเดียวกันด้วยDrawStringวิธีการ หลังจากสร้างบิตแมปที่มีสัญลักษณ์สองรายการแล้วคุณสามารถเปรียบเทียบแบบพิกเซลต่อพิกเซลได้

ข้อดีของวิธีนี้คือคุณสามารถเปรียบเทียบไม่เพียง แต่ตัวอักษรที่เท่ากันหมดเท่านั้น แต่ยังคล้ายกันอีกด้วย (ด้วยค่าเผื่อที่แน่นอน)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.