为什么Guid.NewGuid永远不会产生不包含4的Guid?

The*_*Dag 5 .net guid

人们会认为guid中的字节分布是随机的,或者至少是非常平坦的.Guid.NewGuid总是制造包含4的 guid的原因是什么其字符串表示包含4?

那是

Guid.NewGuid().的ToString( "N").包含( "4")

总是如此.

快速测试表明大多数字节出现在大约85%的Guids中,但是4个出现在100%中.也许这没关系,但我很想知道为什么.

[编辑]
我不是很清楚,所以编辑以提高我的问题的清晰度.


运行这个.不完全是深刻的,但有趣.

using System; using System.Diagnostics;

namespace ConsoleApplication1 { class Program { static bool paused, exit;

    static void Main(string[] args)
    {
        Console.WindowHeight = (int)(0.8*Console.LargestWindowHeight);

        var reportInterval = TimeSpan.FromSeconds(0.15);
        WriteLine(ConsoleColor.White, "X key to exit.");

        Guid guid;
        byte[] bytes;
        long guidCount = 0;
        var counts = new long[256];
        var watch = Stopwatch.StartNew();
        var cursorPos = new CursorLocation();

        while (!exit)
        {
            if (!paused)
            {
                guid = Guid.NewGuid();
                bytes = guid.ToByteArray();
                ++guidCount;

                for (int i = 0; i < 16; i++)
                {
                    var b = bytes[i];
                    ++counts[b];
                }

                if (watch.Elapsed > reportInterval)
                {
                    cursorPos.MoveCursor();
                    DumpFrequencies(counts, guidCount);
                    watch.Restart();
                }
            }

            if (Console.KeyAvailable)
            {
                ProcessKey(Console.ReadKey());
            }
        }
    }


    static void ProcessKey(ConsoleKeyInfo keyInfo)
    {
        switch (keyInfo.Key)
        {
            case ConsoleKey.P:
                paused = !paused;
                break;
            case ConsoleKey.X:
                exit = true;
                break;
        }
    }


    static void DumpFrequencies(long[] byteCounts, long guidCount)
    {
        Write("\r\n{0} GUIDs generated. Frequencies:\r\n\r\n", guidCount);

        const int itemWidth = 9;
        int colCount = Console.WindowWidth / (itemWidth*2);

        for (int i = 0; i < 256; i++)
        {
            var f = (double)byteCounts[i] / (16 * guidCount);
            Write(RightAdjust(itemWidth, "{0:x}", i));
            Write(GetFrequencyColor(f), " {0:p}".PadRight(itemWidth), f);
            if ((i + 1) % colCount == 0) Write("\r\n");
        }
    }


    static ConsoleColor GetFrequencyColor(double f)
    {
        if (f < 0.003) return ConsoleColor.DarkRed;
        if (f < 0.004) return ConsoleColor.Green;
        if (f < 0.005) return ConsoleColor.Yellow;
        return ConsoleColor.White;
    }


    static string RightAdjust(int w, string s, params object[] args)
    {
        if (args.Length > 0)
            s = string.Format(s, args);
        return s.PadLeft(w);
    }

    #region From my library, so I need not include that here...
    class CursorLocation
    {
        public int X, Y;
        public CursorLocation()
        {
            X = Console.CursorLeft;
            Y = Console.CursorTop;
        }

        public void MoveCursor()
        {
            Console.CursorLeft = X;
            Console.CursorTop = Y;
        }
    }


    static public void Write(string s, params object[] args)
    {
        if (args.Length > 0) s = string.Format(s, args);
        Console.Write(s);
    }


    static public void Write(ConsoleColor c, string s, params object[] args)
    {
        var old = Console.ForegroundColor;
        Console.ForegroundColor = c;
        Write(s, args);
        Console.ForegroundColor = old;
    }


    static public void WriteNewline(int count = 1)
    {
        while (count-- > 0) Console.WriteLine();
    }


    static public void WriteLine(string s, params object[] args)
    {
        Write(s, args);
        Console.Write(Environment.NewLine);
    }


    static public void WriteLine(ConsoleColor c, string s, params object[] args)
    {
        Write(c, s, args);
        Console.Write(Environment.NewLine);
    }
    #endregion
}
Run Code Online (Sandbox Code Playgroud)

}

using System; using System.Diagnostics;

namespace ConsoleApplication1 { class Program { static bool paused, exit;

    static void Main(string[] args)
    {
        Console.WindowHeight = (int)(0.8*Console.LargestWindowHeight);

        var reportInterval = TimeSpan.FromSeconds(0.15);
        WriteLine(ConsoleColor.White, "X key to exit.");

        Guid guid;
        byte[] bytes;
        long guidCount = 0;
        var counts = new long[256];
        var watch = Stopwatch.StartNew();
        var cursorPos = new CursorLocation();

        while (!exit)
        {
            if (!paused)
            {
                guid = Guid.NewGuid();
                bytes = guid.ToByteArray();
                ++guidCount;

                for (int i = 0; i < 16; i++)
                {
                    var b = bytes[i];
                    ++counts[b];
                }

                if (watch.Elapsed > reportInterval)
                {
                    cursorPos.MoveCursor();
                    DumpFrequencies(counts, guidCount);
                    watch.Restart();
                }
            }

            if (Console.KeyAvailable)
            {
                ProcessKey(Console.ReadKey());
            }
        }
    }


    static void ProcessKey(ConsoleKeyInfo keyInfo)
    {
        switch (keyInfo.Key)
        {
            case ConsoleKey.P:
                paused = !paused;
                break;
            case ConsoleKey.X:
                exit = true;
                break;
        }
    }


    static void DumpFrequencies(long[] byteCounts, long guidCount)
    {
        Write("\r\n{0} GUIDs generated. Frequencies:\r\n\r\n", guidCount);

        const int itemWidth = 9;
        int colCount = Console.WindowWidth / (itemWidth*2);

        for (int i = 0; i < 256; i++)
        {
            var f = (double)byteCounts[i] / (16 * guidCount);
            Write(RightAdjust(itemWidth, "{0:x}", i));
            Write(GetFrequencyColor(f), " {0:p}".PadRight(itemWidth), f);
            if ((i + 1) % colCount == 0) Write("\r\n");
        }
    }


    static ConsoleColor GetFrequencyColor(double f)
    {
        if (f < 0.003) return ConsoleColor.DarkRed;
        if (f < 0.004) return ConsoleColor.Green;
        if (f < 0.005) return ConsoleColor.Yellow;
        return ConsoleColor.White;
    }


    static string RightAdjust(int w, string s, params object[] args)
    {
        if (args.Length > 0)
            s = string.Format(s, args);
        return s.PadLeft(w);
    }

    #region From my library, so I need not include that here...
    class CursorLocation
    {
        public int X, Y;
        public CursorLocation()
        {
            X = Console.CursorLeft;
            Y = Console.CursorTop;
        }

        public void MoveCursor()
        {
            Console.CursorLeft = X;
            Console.CursorTop = Y;
        }
    }


    static public void Write(string s, params object[] args)
    {
        if (args.Length > 0) s = string.Format(s, args);
        Console.Write(s);
    }


    static public void Write(ConsoleColor c, string s, params object[] args)
    {
        var old = Console.ForegroundColor;
        Console.ForegroundColor = c;
        Write(s, args);
        Console.ForegroundColor = old;
    }


    static public void WriteNewline(int count = 1)
    {
        while (count-- > 0) Console.WriteLine();
    }


    static public void WriteLine(string s, params object[] args)
    {
        Write(s, args);
        Console.Write(Environment.NewLine);
    }


    static public void WriteLine(ConsoleColor c, string s, params object[] args)
    {
        Write(c, s, args);
        Console.Write(Environment.NewLine);
    }
    #endregion
}
Run Code Online (Sandbox Code Playgroud)

}

using System; using System.Diagnostics;

namespace ConsoleApplication1 { class Program { static bool paused, exit;

    static void Main(string[] args)
    {
        Console.WindowHeight = (int)(0.8*Console.LargestWindowHeight);

        var reportInterval = TimeSpan.FromSeconds(0.15);
        WriteLine(ConsoleColor.White, "X key to exit.");

        Guid guid;
        byte[] bytes;
        long guidCount = 0;
        var counts = new long[256];
        var watch = Stopwatch.StartNew();
        var cursorPos = new CursorLocation();

        while (!exit)
        {
            if (!paused)
            {
                guid = Guid.NewGuid();
                bytes = guid.ToByteArray();
                ++guidCount;

                for (int i = 0; i < 16; i++)
                {
                    var b = bytes[i];
                    ++counts[b];
                }

                if (watch.Elapsed > reportInterval)
                {
                    cursorPos.MoveCursor();
                    DumpFrequencies(counts, guidCount);
                    watch.Restart();
                }
            }

            if (Console.KeyAvailable)
            {
                ProcessKey(Console.ReadKey());
            }
        }
    }


    static void ProcessKey(ConsoleKeyInfo keyInfo)
    {
        switch (keyInfo.Key)
        {
            case ConsoleKey.P:
                paused = !paused;
                break;
            case ConsoleKey.X:
                exit = true;
                break;
        }
    }


    static void DumpFrequencies(long[] byteCounts, long guidCount)
    {
        Write("\r\n{0} GUIDs generated. Frequencies:\r\n\r\n", guidCount);

        const int itemWidth = 9;
        int colCount = Console.WindowWidth / (itemWidth*2);

        for (int i = 0; i < 256; i++)
        {
            var f = (double)byteCounts[i] / (16 * guidCount);
            Write(RightAdjust(itemWidth, "{0:x}", i));
            Write(GetFrequencyColor(f), " {0:p}".PadRight(itemWidth), f);
            if ((i + 1) % colCount == 0) Write("\r\n");
        }
    }


    static ConsoleColor GetFrequencyColor(double f)
    {
        if (f < 0.003) return ConsoleColor.DarkRed;
        if (f < 0.004) return ConsoleColor.Green;
        if (f < 0.005) return ConsoleColor.Yellow;
        return ConsoleColor.White;
    }


    static string RightAdjust(int w, string s, params object[] args)
    {
        if (args.Length > 0)
            s = string.Format(s, args);
        return s.PadLeft(w);
    }

    #region From my library, so I need not include that here...
    class CursorLocation
    {
        public int X, Y;
        public CursorLocation()
        {
            X = Console.CursorLeft;
            Y = Console.CursorTop;
        }

        public void MoveCursor()
        {
            Console.CursorLeft = X;
            Console.CursorTop = Y;
        }
    }


    static public void Write(string s, params object[] args)
    {
        if (args.Length > 0) s = string.Format(s, args);
        Console.Write(s);
    }


    static public void Write(ConsoleColor c, string s, params object[] args)
    {
        var old = Console.ForegroundColor;
        Console.ForegroundColor = c;
        Write(s, args);
        Console.ForegroundColor = old;
    }


    static public void WriteNewline(int count = 1)
    {
        while (count-- > 0) Console.WriteLine();
    }


    static public void WriteLine(string s, params object[] args)
    {
        Write(s, args);
        Console.Write(Environment.NewLine);
    }


    static public void WriteLine(ConsoleColor c, string s, params object[] args)
    {
        Write(c, s, args);
        Console.Write(Environment.NewLine);
    }
    #endregion
}
Run Code Online (Sandbox Code Playgroud)

}

我有一天需要学习如何正确地格式化东西.Stackoverflow是grrr-eat.

Mar*_*tin 8

GUID不是完全随机的,4的位置表示生成的GUID的"类型".

请参见http://en.wikipedia.org/wiki/Globally_unique_identifier