تقييم الموضوع :
  • 0 أصوات - بمعدل 0
  • 1
  • 2
  • 3
  • 4
  • 5
بناء نظام ترميز ثنائي Binary Encoding
#1
مقدمة
في هذا الموضوع سنوضح كيفية بناء نظام ترميز ثنائي من الصفر بدون أن تعتمد علي الكلاسات الموجودة في الدوت نت إلا في ما تيسر مثل استخدام الأساسيات فقط من الأنواع التالية
String او Long أو Integer أو Byte أو المصفوفات .... الخ

والفكرة هنا يمكن تقسيمها الي مرحلتين
المرحلة الأولي:
تحويل حرف أبجدي الي رقم و هذا الرقم قد يكون من النوع Integer أو من النوع Long عموما تحديد النوع راجع لك
مثلا أنا شخصيا أفضل النوع Long حتي يكون الكود الخاص بي يدعم الحروف الانجليزية و العربية معا
المرحلة الثانية:
استعادة الحرف الأبجدي من هذا الرقم

وللتوضيح أكثر قليلا فإنه يمكن تفسيير الأمر كالتالي

1- نحدد الحرف الأبجدي
2- نحصل علي قيمة الأسكي الخاصة بهذا الحرف ونقوم بتحويلها إلي بيناري تكست
3- نقوم بتحويل البيناري تكست الي رقم هذا الرقم مثلا قد يكون من النوع Long
4- و بعد ذلك و بعملية عكسية نعيد الرقم الي حرف أبجدي مرة ثانية
بشكل عام هذا الموضوع ممكن اعتباره أساس جيد للاستخدام في موضوعات مثل الباركود او في ضغط البيانات او في تغيير شكل البيانات

مثال توضيحي:
الحرف الأبجدي ------------------------------------------------------------------------------------------- A
رقم الأسكي الخاص به يساوي ------------------------------------------------------------------------ 65
وعند تجويله مثلا الي بيناري تكست قد يعطينا الشكل ----------------------------------------------- 001000001
وعند تحويل البيناري تكست الي رقم يمكننا أن نحصل علي الشكل هذا --------------------------- 20115011
أو يمكن أن نحصل علي الشكل هذا -------------------------------------------------------------------  2151
أو يمكن أن نحصل علي الشكل هذا -------------------------------------------------------------------------  215100

عموما الفكرة تنحصر في حساب عدد مرات تكرار الرقم في البيناري تكست
ثم بعد ذلك نصيف الحرف المتكرر علي يمين هذا الرقم

مثلا الييناري   00000011
الصفر متكرر 6 مرات و الرقم واحد متكرر مرتين و بالتالي نحصل علي الرقم 6021
حيث الرفم 6 يمثل عدد مرات تكرار الرقم صفر و الحرف الثاني هو الرقم صفر نفسه فنحصل غلي 60
و الرقم 2 هو عدد مرات تكرار الرقم واحد و الحرف الذي يليه هو الرقم واحد نفسه فنحصل علي  21
ويتم دمجهم معا فنحصل غلي الرقم 6021

أو يمكن الاستغناء عن اضافة الحرف الأبجدي تماما
مثلا البيناري اعلاه 00000011
يمكن تحويله الي الرقم 62
وهنا نحن نحسب عدد مرات التكرار فقط بدون أن نضيف الحرف صفر او الحرف واحد

الكود:
الكود التالي يوضح واحدة من الطرق للتعامل مع الحروف الأبجدية و تحويلها الي بيناري ثم الي رقم
PHP كود :
       ' تعريف الحرف الأبجدي
        Dim chr As Char = "A"c
        ' 
تحويل الحرف الأبجدي الي أسكي
        Dim code 
As Integer AscW(chr)

 
       ' تحويل قيمة الأسكي الي بيناري تكست
        Dim binary As String = String.Empty
        While code > AscW(Char.MinValue)
            Dim v As Integer = (code And 1)
            binary = v.ToString + binary
            code = code >> 1
        End While
        ' 
تحديد عدد الأصفار المطلوب اضافتها علي يسار البيناري تكست
        
' من الأفضل أن لايقل عدد الأصفار عن 2 و أيضا لا يزيد عن 8
        Dim padWidth As Integer = 2
        ' 
إضافة مجموعة من الأصفار علي يسار البيناري تكست
        binary 
binary.PadLeft(binary.Length padWidth"0"c)

 
       ' إحسب عدد مرات تكرار كل حرف في البيناري و أضفهم الي مصفوفة
        Dim values As List(Of Integer) = New List(Of Integer)()
        Dim count As Integer = 1
        Dim current As Char = binary(0)
        Dim i As Integer = 1
        While (i < binary.Length)
            If (current = binary(i)) Then
                count = (count + 1)
            Else
                values.Add(count)
                count = 1
                current = binary(i)
            End If
            i = (i + 1)
        End While
        values.Add(count)

        ' 
تحويل المصفوفة الي تكست
        Dim result 
As String String.Empty
 
       For Each v As Integer In values
            result 
+= v.ToString
        Next

        
' لو أن رقم الأسكي عبارة عن رقم فردي أضف صفران في اخر الناتج
        ' 
لو أن رقم الأسكي عبارة عن رقم زوجي أضف صفرا واحدا في أخر الناتج
        
' الفكرة من استخدام هذه الطريقة هي أن نتمكن من استرداد قيمة حرف الأسكي لاحقا
        result = If(code Mod 2 <> 0, result + New String("0", 2), result + New String("0")) 


الكود أعلاه يمكن تحويله الي دوال كالتالي

PHP كود :
   Private Function ZipToString(chr As Char) As String

        Dim code 
As Integer AscW(chr)
 
       Dim binary As String String.Empty
 
       While code AscW(Char.MinValue)
 
           Dim v As Integer = (code And 1)
 
           binary v.ToString binary
            code 
code >> 1
        End 
While
 
       Dim padWidth As Integer 2
        binary 
binary.PadLeft(binary.Length padWidth"0"c)

 
       Dim values As List(Of Integer) = New List(Of Integer)()
 
       Dim count As Integer 1
        Dim current 
As Char binary(0)
 
       Dim i As Integer 1
        While 
(binary.Length)
 
           If (current binary(i)) Then
                count 
= (count 1)
 
           Else
                values
.Add(count)
 
               count 1
                current 
binary(i)
 
           End If
 
           i = (1)
 
       End While
 
       values.Add(count)

 
       Dim result As String String.Empty
 
       For Each v As Integer In values
            result 
+= v.ToString
        Next

        result 
= If(code Mod 2 <> 0result + New String("0"2), result + New String("0"))
 
       Return result
    End 
Function

 
   Private Function ZipToLong(value As Char) As Long
        Return Long
.Parse(Me.ZipToString(value))
 
   End Function 

أتمني أن يكون الموضوع مفيدا للبعض منكم
ولاحقا سوف أكمل بقية الموضوع
تقبلوا تحياتي
Retired
الرد }}}
تم الشكر بواسطة: sendbad100 , ابو ليلى
#2
جميل اخي العزيز هذا الموضوع مهم ومتشعب جداً
ممكن تفيدك الصورة التالية


الملفات المرفقة صورة/صور
   
الرد }}}
تم الشكر بواسطة: sendbad100 , ابو ليلى
#3
شكرا لك علي جدول الأسكي

حسابات الاسكي نممكن تنفيذها باستخدام الكود التالي

مثلا للحرف الانجليزي A

كود :
       Dim chr As Char = "A"c
       Dim code As Integer = AscW(chr)
       Dim binary As String = String.Empty
       While code > AscW(Char.MinValue)
           Dim v As Integer = (code And 1)
           binary = v.ToString + binary
           code = code >> 1
       End While

و نفس الكود يمكن استخدامه مع الحروف العربية
مثلا للحرف العربي ب

PHP كود :
       Dim chr As Char "ب"c
        Dim code 
As Integer AscW(chr)
 
       Dim binary As String String.Empty
 
       While code AscW(Char.MinValue)
 
           Dim v As Integer = (code And 1)
 
           binary v.ToString binary
            code 
code >> 1
        End 
While 

لكن ومن أجل بناء نظام ترميز من الصفر
نحتاج ان نقوم بعمل Pad لهذا البيناري تكست ونضع عدد معين من الأصفار علي يساره
وهذا لسهولة استرداد الحرف لاحقا بعد ترميزه

شكرا لمشاركتك اخي الفاضل
Retired
الرد }}}
تم الشكر بواسطة: khodor1985 , khodor1985 , sendbad100 , ابو ليلى
#4
في المشاركة السابقة تم توضيح كيفية تحويل الحرف الأبجدي الي رقم
و الخلاصة من الجزء الأول تنحصر في الدوال التالية

ملحوظة :
يجب أن تضع في اعتبارك دائما ان الحروف الأبجدية و التي رقم الأسكي الخاص بها عبارة عن رقم زوجي تعطي رقم أكبر من الحروف الأبجدية التي رقم الأسكي الخاص بها عبارة عن رقم فردي 
ولقد تم التعديل علي الكود قليلا لتفادي هذه المشكلة

الدوال: 
1- تحويل الحرف الي بيناري 

PHP كود :
   Private Function ConvertToBinary(code As Integer) As String
        Dim result 
As String String.Empty
 
       While code AscW(Char.MinValue)
 
           Dim v As Integer = (code And 1)
 
           result v.ToString result
            code 
code >> 1
        End 
While
 
       Return result
    End 
Function 

2- تحويل البيناري الي رقم
PHP كود :
   Private Function Zip(binary As String) As String

        Dim values 
As List(Of Integer) = New List(Of Integer)()
 
       Dim count As Integer 1
        Dim current 
As Char binary(0)
 
       Dim i As Integer 1
        While 
(binary.Length)
 
           If (current binary(i)) Then
                count 
= (count 1)
 
           Else
                values
.Add(count)
 
               count 1
                current 
binary(i)
 
           End If
 
           i = (1)
 
       End While
 
       values.Add(count)

 
       ' لتفادي مشكلة الحروف التي لها قيمة أسكي عبارة عن رقم زوجي أو فردي
        If (values.Count - 1) Mod 2 = 0 Then
            values.Add(0)
        End If

        ' 
تحويل المصفوفة الي تكست
        Dim result 
As String String.Empty
 
       For Each v As Integer In values
            result 
+= v.ToString
        Next
        Return result
    End 
Function 

الإستخدام

PHP كود :
       Dim chr As Char "b"c
        Dim code 
As Integer AscW(chr)
 
       Dim binary As String Me.ConvertToBinary(code)
 
       Dim padWidth As Integer 2
        binary 
binary.PadLeft(binary.Length padWidth"0"c)
 
       Dim zipped As String Me.Zip(binary) 


عملية استرجاع الحرف مرة ثانية من الرقم
تعتمد علي تحويل الرقم الي بيناري
ثم تحويل البيناري الي رقم يمثل رقم الأسكي الخاص بالحرف الأبجدي
و يمكنكم استخدام الدول التالية

الدوال:
1- تحويل الرقم الي بيناري ثانية
وهنا نعيد بناء البيناري من الحروف التي هي عبارة عن ارقام
PHP كود :
   Private Function UnZip(As String) As String
        Dim result 
As String ""
 
       Dim i As Integer 0
        While i 
s.Length
            result 
+= New String("0"cCInt(s(i).ToString))
 
           result += New String("1"cCInt(s(1).ToString))
 
           i = (2)
 
       End While
 
       Return result
    End 
Function 

2- تحويل البيناري الي رقم الأسكي ثانية

PHP كود :
   Private Function ConvertFromBinary(As String) As Integer
        Dim result 
As Integer 0
        Dim values 
As Char() = s.Reverse.ToArray
        Dim i 
As Integer 0
        While i 
values.Length
            If values
(i) = "1"c Then
                result 
CInt(Math.Pow(2i)) + result
            End 
If
 
           i = (1)
 
       End While
 
       Return result
    End 
Function 

الإستخدام

PHP كود :
       '  تحويل الرقم الي بيناري مرة ثانية 
        Dim unzipped As String = Me.UnZip(zipped)
        ' 
تحويل البيناري الي رقم
        Dim value 
As String Me.ConvertFromBinary(unzipped)
 
       ' تحويل الرقم الي حرف مرة ثانية
        Dim result As Char = ChrW(CInt(value)) 


المثال التالي يوضخ كيفية تحويل كلمة واخدة الي أرقام 
باستخدام الدوال اعلاه

PHP كود :
       Dim binaryValue As String String.Empty
 
       Dim s As String "abcds"
 
       Dim chars As Char() = s.ToCharArray
        For i 
0 To chars.Length 1
            Dim c 
As Char chars(i)
 
           Dim asciCode As Integer AscW(c)
 
           Dim b As String Me.ConvertToBinary(asciCode)
 
           Dim pad As Integer 4
            b 
b.PadLeft(b.Length pad"0"c)
 
           binaryValue += Me.Zip(b)
 
           binaryValue += " "c
        Next
        binaryValue 
binaryValue.TrimEnd(" "c
لو نظرت الي الناتج اعلاه ستجد ان الحروف التي لها رقم اسكي فردي تعطي قيمة اقل من الحروف التي لها رقم اسكي زوجي
و لتفادي ذلك يمكن التعديل قليلا علي الدالة الي تقوم بتحويل البيناري الي رقم لتكون كالتالي 

PHP كود :
  Private Function Zip(binary As String) As String

        Dim values 
As List(Of Integer) = New List(Of Integer)()
 
       Dim count As Integer 1
        Dim current 
As Char binary(0)
 
       Dim i As Integer 1
        While 
(binary.Length)
 
           If (current binary(i)) Then
                count 
= (count 1)
 
           Else
                values
.Add(count)
 
               count 1
                current 
binary(i)
 
           End If
 
           i = (1)
 
       End While
 
       values.Add(count)

 
       ' لتفادي مشكلة الحروف التي لها قيمة أسكي عبارة عن رقم زوجي أو فردي
        If (values.Count - 1) Mod 2 = 0 Then
            values.Add(0)
        Else
            values.Add(0)
            values.Add(0)
        End If

        ' 
تحويل المصفوفة الي تكست
        Dim result 
As String String.Empty
 
       For Each v As Integer In values
            result 
+= v.ToString
        Next
        Return result
    End 
Function 

أعتقد أنه لن يكون صعبا علي القارئ أن يقوم باسترجاع البيانات مرة ثانية
ملحوظة هامة:
لا تحاول تحويل مجموعة من الكلمات باستخدام الأسلوب اعلاه لأن الأمر يختاج الي كتابة المزيد من الدول و لهذا حديث أخر

طبعا الموضوع مجرد توضيح لبعض الأفكار و هناك اساليب اخري لتحويل الحرف الي ارقام و هذا متروك لمخيلة القارئ و فهمه الجيد للفكرة التي طرحناها

تقبلوا تحياتي
Retired
الرد }}}
تم الشكر بواسطة: sendbad100



التنقل السريع :


يقوم بقرائة الموضوع: