C# :: Aufgabe #172

3 Lösungen Lösungen öffentlich

Gray-Code bei Analog-Digital-Konvertierung

Anfänger - C# von hollst - 15.04.2017 um 15:00 Uhr
Bei der Analog-Digital-Konvertierung sollte die Abtastfrequenz in der Regel
wesentlich höher sein als die zeitliche Änderung des Messsignals (Nyquist-Kriterium).
Aus diesem Grunde ergeben zwei benachbarte Abtastungen zumeist entweder den gleichen (Digital)wert
oder einen um +/- 1 geänderten Wert. Ist dies nicht der Fall, so kann man mit sehr hoher
Wahrscheinlichkeit von einem Fehler bei der Messung (größer Rauscheinfluss) oder bei der Analog-
Digital-Konvertierung ausgehen.

Fehler bei der Analog-Digital-Konvertierung können bevorzugt dann entstehen, wenn bei einer
Messwertänderung um +/- 1 gleichzeitig mehrere Binärwerte switschen müssen. Z. B. bei einem
Messwert 7, der sich auf 8 ändert (7 -> 8) ändert sich der Binärwert von 0111 -> 1000, d. h.
es müssen quasi parallel vier Bits gekippt werden.

Um diese Fehlerquelle zu minimieren, werden die Messwerte zumeist nicht direkt in eine
Binärzahl konvertiert, sondern zunächst in den sogenannten Gray-Code. Der Gray-Code garantiert, dass sich bei
einer Messwertänderung um +/- 1 nur ein einziges Bit im Code ändert.

Das Kodierungsschema lässt sich u. a. leicht aus folgender Tabelle ableiten:

Dezimal Binär-Code Gray-Code

00 0000 0000
01 0001 0001
02 0010 0011
03 0011 0010
04 0100 0110
05 0101 0111
06 0110 0101
07 0111 0100
08 1000 1100
09 1001 1101
10 1010 1111
11 1011 1110
12 1100 1010
13 1101 1011
14 1110 1001
15 1111 1000

Wie ersichtlich, switscht bei der Gray-Kodierung lediglich ein Bit, wenn sich die Dezimal-Kodierung
um eine Einheit ändert.

Der Gray-Code geht auf einen Herren namens Frank Gray (1887 -1969) zurück, der sich den Code 1953
patentieren ließ, obwohl er in der Mathematik längst bekannt war. Aus meiner Sicht eine sehr bedenkliche Patenterteilung.

Die Programmierungsaufgabe besteht darin ein Programm zu schreiben,
das ein positives Integer entgegennimmt und die Gray-Code-Folge zurückgibt.

Optional kann auch die inverse Transformation programmiert werden.

Lösungen:

vote_ok
von daniel59 (4260 Punkte) - 18.04.2017 um 10:43 Uhr
Quellcode ausblenden C#-Code
using System;

namespace ConsoleGrayCode
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("--- Gray-Code ---");
            uint i;
            bool loop = true;
            do
            {
                Console.Write("Geben Sie eine positive Zahl ein: ");
                loop = uint.TryParse(Console.ReadLine(), out i);
                string grayCode;
                uint transform;
                if (loop)
                {
                    grayCode = ToGrayCode(i);
                    transform = FromGrayCode(grayCode);
                    Console.WriteLine("Gray-Code: {0} \tRücktransformiert: {1}", grayCode, transform);
                }
                else
                {
                    Console.WriteLine("Bitte nur positive Zahlen eingeben.\nDas Programm wird beendet.");
                }
            }
            while (loop);

            Console.ReadKey();
        }

        static string ToGrayCode(uint i)
        {
            return Convert.ToString((i >> 1) ^ i, 2);
        }

        static uint FromGrayCode(string code)
        {
            uint v = Convert.ToUInt32(code, 2);

            int index = code.IndexOf('1');
            if (index == -1)
            { return 0; }
            int l = 4;
            for (int i = l; i >= 0; i--)
            {
                v = v ^ (v >> (int)Math.Pow(2, i));
            }

            return v;
        }
    }
}
vote_ok
von Rubbellos (70 Punkte) - 24.04.2017 um 17:27 Uhr
Ich habe das System jetzt als Hexadezimal-System gewertet und mein Programm so geschrieben das es jede beliebige Zahl in einen Gray Code auf Hexadezimal-Basis umwertet. Also 16 ist z.B. 00 (0000 0000 im Gray Code).
Quellcode ausblenden C#-Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GrayCode
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Welche Zahl soll als GrayCode ausgegeben werden?");
            int Number = Convert.ToInt32(Console.ReadLine());
            Converter Hex = new Converter();
            int Size = 1;
            Hex.CheckSize(Number, ref Size);
            int[] resultHex = new int[Size];
            string[] resultGray = new string[Size];
            Hex.ConvertingToHex(Number, ref resultHex);
            Hex.ConvertingToGray(resultHex, ref resultGray);
            Console.WriteLine("GrayCode:");
            for(int i = 1; i < Size+1; i++)
            {
                Console.WriteLine(resultGray[Size - i]);
            }
            Console.ReadLine();
        }
    }
    class Converter
    {
        public void CheckSize(int Num, ref int Size)
        {
            while (Num > 1)
            {

                if (Num <= 15)
                {
                    Num = 0;
                }
                else
                {
                    Size++;
                    Num = Num / 16;
                }
            }
        }
        public void ConvertingToHex(int Num, ref int[] Numbers)
        {
            int j = 0;
            while (Num > 1)
            {
                
                if (Num <= 15)
                {
                    Numbers[j] = Num;
                    Num = 0;
                }
                else
                {
                Numbers[j] = Num%16;
                Num = Num / 16;
                j++;
                }
            }
        }
        public void ConvertingToGray(int[] Numbers, ref string[] result)
        {
            int lauf = 0;
            foreach(int k in Numbers)
            {
                switch(k)
                {
                    case 0: result[lauf] = "0000"; break;
                    case 1: result[lauf] = "0001"; break;
                    case 2: result[lauf] = "0011"; break;
                    case 3: result[lauf] = "0010"; break;
                    case 4: result[lauf] = "0110"; break;
                    case 5: result[lauf] = "0111"; break;
                    case 6: result[lauf] = "0101"; break;
                    case 7: result[lauf] = "0100"; break;
                    case 8: result[lauf] = "1100"; break;
                    case 9: result[lauf] = "1101"; break;
                    case 10: result[lauf] = "1111"; break;
                    case 11: result[lauf] = "1110"; break;
                    case 12: result[lauf] = "1010"; break;
                    case 13: result[lauf] = "1011"; break;
                    case 14: result[lauf] = "1001"; break;
                    case 15: result[lauf] = "1000"; break;
                }
                lauf++;
            }
        }
    }
}
vote_ok
von hollst (13980 Punkte) - 27.04.2017 um 08:31 Uhr
Quellcode ausblenden C#-Code
using System;
using static System.Console;

namespace gray_code { 

    class Program    {

        static string NL = Environment.NewLine;
        static void Main()        {

            bool bo_exit = false;
            while (!bo_exit)            {
                uint input = 0;

                bool bo_input_ok = false;
                while (!bo_input_ok)                {
                    string sinput = (NL + "give me an uint for gray coding: ").Message();
                    bo_input_ok = uint.TryParse(sinput, out input);
                }

                WriteLine("gray  : " + BinaryToGray(input).Convert());
                WriteLine("binary: " + input.GetBinaryString());
                
                ConsoleKeyInfo ki ="again? exit with ESC".EndMessage();
                bo_exit = ki.Key == ConsoleKey.Escape;
            }
        }

        static uint BinaryToGray(uint num)        {
            return (num >> 1) ^ num;
        }
    }

    public static class MyExtensions    {

        public static ConsoleKeyInfo EndMessage(this string s)        {
            Write(s); return ReadKey(true);
        }

        public static string Message(this string s)        {
            Write(s); return ReadLine();
        }

        public static string Convert(this uint x)        {

            char[] bits = new char[32];
            int i = 0;

            while (x != 0)            {
                bits[i++] = (x & 1) == 1 ? '1' : '0';
                x >>= 1;
            }

            Array.Reverse(bits, 0, i);
            return new string(bits);
        }

        // Convert Integer to binary and return as string
        public static string GetBinaryString(this uint n)
        {
            char[] b = new char[sizeof(Int32) * 8];

            for (int i = 0; i < b.Length; i++)
                b[b.Length - 1 - i] = ((n & (1 << i)) != 0) ? '1' : '0';

            return new string(b).TrimStart('0');
        }
    }
}