2012-03-08 7 views
5

Si direbbe che la distribuzione dei byte nei guids fosse casuale, o almeno molto piatta. Qual è la ragione per cui Guid.NewGuid crea sempre i GUID che contengono un 4? la cui rappresentazione stringa contiene un 4?Perché Guid.NewGuid non genera mai un Guid che non contiene un 4?

Questo è

Guid.NewGuid(). ToString ("N"). Contiene ("4")

è sempre vero.

I test rapidi indicano che la maggior parte dei byte si verifica in circa l'85% di Guids, ma 4 si verifica nel 100%. Forse questo non importa, ma mi piacerebbe sapere perché.

[Modifica]
Non ero molto chiaro, così modificato per migliorare la chiarezza della mia domanda.


Eseguire questo. Non esattamente profondo, ma divertente.

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 
} 

}

ho bisogno di imparare come formattare correttamente roba qui un giorno. Stackoverflow è grrr-eat.

+5

[GUID non sono casuali] (http://en.wikipedia.org/wiki/GUID#Algorithm). –

+0

@KonradRudolph Ecco perché ero così specifico riguardo alla distribuzione di byte casuali ** o ** almeno molto piatti. Sapevo che non erano del tutto casuali, anche se non perché. –

+2

Smettila di bruciare i nostri guids! – U1199880

risposta

8

GUID non sono completamente casuali, il punto in cui il 4 indica il "tipo" di GUID generato.

Vedi http://en.wikipedia.org/wiki/Globally_unique_identifier

+1

Grande. Mi sono imbattuto in questo caso quando ho creato un controllo ad albero con supporto per la ricerca come tipo. Per testare, ho creato alberi enormi e quasi casuali, usando ToString ("N") su Guid per ottenere i testi che potevo cercare. Il controllo mostra quante partite ci sono, evidenzia i nodi corrispondenti, scorre la prima partita in vista e consente all'utente di navigare accanto/precedente (w/wrap-around). Ha funzionato bene, ma sono rimasto molto sorpreso di vedere 100.000 partite nell'albero dei 100.000 nodi quando ho digitato "4". :) –

Problemi correlati