{"id":766,"date":"2010-02-27T22:00:24","date_gmt":"2010-02-28T02:00:24","guid":{"rendered":"http:\/\/2d823b65bb.nxcli.io\/?p=766"},"modified":"2018-11-17T11:20:53","modified_gmt":"2018-11-17T16:20:53","slug":"microsoft-random-browser-ballot","status":"publish","type":"post","link":"https:\/\/www.robweir.com\/blog\/2010\/02\/microsoft-random-browser-ballot.html","title":{"rendered":"Doing the Microsoft Shuffle: Algorithm Fail in Browser Ballot"},"content":{"rendered":"<p>March 6th Update:\u00a0 Microsoft appears to have updated the <a href=\"http:\/\/www.browserchoice.eu\/\">www.browserchoice.eu<\/a> website and corrected the error I describe in this post.\u00a0 More details on the fix can be found in <a href=\"https:\/\/2d823b65bb.nxcli.io\/blog\/2010\/03\/new-microsoft-shuffle.html\">The New &amp; Improved Microsoft Shuffle<\/a>.\u00a0 However, I think you will still find the following analysis interesting.<\/p>\n<p>-Rob<\/p>\n<hr \/>\n<h3>Introduction<\/h3>\n<p>The story first hit in last week on the Slovakian tech site <a href=\"http:\/\/www.dsl.sk\/article.php?article=8770\">DSL.sk<\/a>.\u00a0 Since I am not linguistically equipped to follow the Slovakian tech scene, I didn&#8217;t hear about the story until it was brought up in English on <a href=\"http:\/\/techcrunch.com\/2010\/02\/22\/microsoft-ballot-screen\/\">TechCrunch<\/a>.\u00a0 The gist of these reports is this: DSL.sk did a test of the &#8220;ballot&#8221; screen at <a href=\"http:\/\/www.browserchoice.eu\/\">www.browserchoice.eu<\/a>, used in Microsoft Windows 7 to prompt the user to install a browser.\u00a0 It was a Microsoft concession to the EU, to provide a randomized ballot screen for users to select a browser.\u00a0 However, the DSL.sk test suggested that the ordering of the browsers was far from random.<\/p>\n<p>But this wasn&#8217;t a simple case of Internet Explorer showing up more in the first position.\u00a0 The non-randomness was pronounced, but more complicated.\u00a0 For example, Chrome was more likely to show up in one of the first 3 positions.\u00a0 And Internet Explorer showed up 50% of the time in the last position.\u00a0 This isn&#8217;t just a minor case of it being slightly random.\u00a0 Try this test yourself: Load <a href=\"http:\/\/www.browserchoice.eu\/\">www.browserchoice.eu<\/a>, in Internet Explorer, and press refresh 20 times.\u00a0 Count how many times the Internet Explorer choice is on the far right.\u00a0\u00a0 Can this be right?<\/p>\n<p>The DLS.sk findings have lead to various theories, made on the likely mistaken theory that this is an intentional non-randomness.\u00a0 Does Microsoft have secret research showing that the 5th position is actually chosen more often?\u00a0 Is the Internet Explorer random number generator not random?\u00a0 There were also comments asserting that the tests proved nothing, and the results were just chance, and others saying that the results are expected to be non-random because computers can only make pseudo-random numbers, not genuinely random numbers.<\/p>\n<p>Maybe there was cogent technical analysis of this issue posted someplace, but if there was, I could not find it.\u00a0 So I&#8217;m providing my own analysis here, a little statistics and a little algorithms 101.\u00a0 I&#8217;ll tell you what went wrong, and how Microsoft can fix it.\u00a0 In the end it is a rookie mistake in the code, but it is an interesting mistake that we can learn from, so I&#8217;ll examine it in some depth.<\/p>\n<h3>Are the results random?<\/h3>\n<p>The ordering of the browser choices is determined by <a href=\"https:\/\/2d823b65bb.nxcli.io\/blog\/attachments\/shuffle\/page.js\">JavaScript code<\/a> on the BrowserChoice.eu web site.\u00a0 You can see the core function in the GenerateBrowserOrder function.\u00a0 I took that function and supporting functions,\u00a0 put it into my own HTML file, added some test driver code and ran it for 10,000 iterations on Internet Explorer.\u00a0 The results are as follows:<\/p>\n<table border=\"1\">\n<caption>Internet Explorer raw counts<\/caption>\n<tbody>\n<tr>\n<th>Position<\/th>\n<th>I.E.<\/th>\n<th>Firefox<\/th>\n<th>Opera<\/th>\n<th>Chrome<\/th>\n<th>Safari<\/th>\n<\/tr>\n<tr>\n<td>1<\/td>\n<td>1304<\/td>\n<td>2099<\/td>\n<td>2132<\/td>\n<td>2595<\/td>\n<td>1870<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>1325<\/td>\n<td>2161<\/td>\n<td>2036<\/td>\n<td>2565<\/td>\n<td>1913<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td>1105<\/td>\n<td>2244<\/td>\n<td>1374<\/td>\n<td>3679<\/td>\n<td>1598<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>1232<\/td>\n<td>2248<\/td>\n<td>1916<\/td>\n<td>590<\/td>\n<td>4014<\/td>\n<\/tr>\n<tr>\n<td>5<\/td>\n<td>5034<\/td>\n<td>1248<\/td>\n<td>2542<\/td>\n<td>571<\/td>\n<td>605<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table border=\"1\">\n<caption>Internet Explorer fraction of total<\/caption>\n<tbody>\n<tr>\n<th>Position<\/th>\n<th>I.E.<\/th>\n<th>Firefox<\/th>\n<th>Opera<\/th>\n<th>Chrome<\/th>\n<th>Safari<\/th>\n<\/tr>\n<tr>\n<td>1<\/td>\n<td>0.1304<\/td>\n<td>0.2099<\/td>\n<td>0.2132<\/td>\n<td>0.2595<\/td>\n<td>0.1870<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>0.1325<\/td>\n<td>0.2161<\/td>\n<td>0.2036<\/td>\n<td>0.2565<\/td>\n<td>0.1913<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td>0.1105<\/td>\n<td>0.2244<\/td>\n<td>0.1374<\/td>\n<td>0.3679<\/td>\n<td>0.1598<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>0.1232<\/td>\n<td>0.2248<\/td>\n<td>0.1916<\/td>\n<td>0.0590<\/td>\n<td>0.4014<\/td>\n<\/tr>\n<tr>\n<td>5<\/td>\n<td>0.5034<\/td>\n<td>0.1248<\/td>\n<td>0.2542<\/td>\n<td>0.0571<\/td>\n<td>0.0605<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>This confirms the DSL.sk results.\u00a0 Chrome appears more often in one of the first 3 positions and I.E. is most likely to be in the 5th position.<\/p>\n<p>You can also see this graphically in a 3D bar chart:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" title=\"Microsoft Shuffle\" src=\"https:\/\/2d823b65bb.nxcli.io\/blog\/attachments\/shuffle\/microsoft.png\" alt=\"\" width=\"634\" height=\"471\" \/><\/p>\n<p>But is this a statistically significant result?\u00a0 I think most\u00a0 of us have an intuitive feeling that results are more significant if many tests are run, and if the results also vary much from an even distribution of positions.\u00a0 On the other hand, we also know that a finite run of even a perfectly random algorithm will not give a perfectly uniform distribution.\u00a0 It would be quite unusual if every cell in the above table was exactly 2,000.<\/p>\n<p>This is not a question one answers with debate.\u00a0 To go beyond intuition you need to perform a statistical test.\u00a0 In this case, a good test is Pearson&#8217;s Chi-square test, which tests how well observed results match a specified distribution.\u00a0 In this test we assume the null-hypothesis that the observed data is taken from a uniform distribution.\u00a0 The test then tells us the probability that the observed results can be explained by chance.\u00a0 In other words, what is the probability that the difference between observation and a uniform distribution was just the luck of the draw?\u00a0 If that probability is very small, say less than 1%, then we can say with high confidence, say 99% confidence, that the positions are not uniformly distributed. \u00a0 However, if the test returns a larger number, then we cannot disprove our null-hypothesis.\u00a0 That doesn&#8217;t mean the null-hypothesis is true.\u00a0 It just means we can&#8217;t disprove it.\u00a0 In the end we can never prove the null hypothesis.\u00a0 We can only try to disprove it.<\/p>\n<p>Note also that having a uniform distribution is not the same as having uniformly distributed random positions.\u00a0 There are ways of getting a uniform distribution that are not random, for example, by treating the order as a circular buffer and rotating through the list on each invocation.\u00a0 Whether or not randomization is needed is ultimately dictated by the architectural assumptions of your application.\u00a0 If you determine the order on a central server and then serve out that order on each innovation, then you can use non-random solutions, like the rotating circular buffer.\u00a0 But if the ordering is determined independently on each client, for each invocation, then you need some source of randomness on each client to achieve a uniform distribution overall.\u00a0 But regardless of how you attempt to achieve a uniform distribution the way to test it is the same, using the Chi-square test.<\/p>\n<p>Using the open source statistical package <a href=\"http:\/\/www.r-project.org\/\">R<\/a>, I ran the\u00a0 chisq.test() routine on the above data.\u00a0 The results are:<\/p>\n<pre>X-squared = 13340.23, df = 16, p-value &lt; 2.2e-16<\/pre>\n<p>The p-value is much, much less than 1%.\u00a0 So, we can say with high confidence that the results are not random.<\/p>\n<p>Repeating the same test on Firefox is also non-random, but in a different way:<\/p>\n<table border=\"1\">\n<caption>Firefox raw counts<\/caption>\n<tbody>\n<tr>\n<th>Position<\/th>\n<th>I.E.<\/th>\n<th>Firefox<\/th>\n<th>Opera<\/th>\n<th>Chrome<\/th>\n<th>Safari<\/th>\n<\/tr>\n<tr>\n<td>1<\/td>\n<td>2494<\/td>\n<td>2489<\/td>\n<td>1612<\/td>\n<td>947<\/td>\n<td>2458<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>2892<\/td>\n<td>2820<\/td>\n<td>1909<\/td>\n<td>1111<\/td>\n<td>1268<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td>2398<\/td>\n<td>2435<\/td>\n<td>2643<\/td>\n<td>1891<\/td>\n<td>633<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>1628<\/td>\n<td>1638<\/td>\n<td>2632<\/td>\n<td>3779<\/td>\n<td>323<\/td>\n<\/tr>\n<tr>\n<td>5<\/td>\n<td>588<\/td>\n<td>618<\/td>\n<td>1204<\/td>\n<td>2272<\/td>\n<td>5318<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table border=\"1\">\n<caption>Firefox fraction of total<\/caption>\n<tbody>\n<tr>\n<th>Position<\/th>\n<th>I.E.<\/th>\n<th>Firefox<\/th>\n<th>Opera<\/th>\n<th>Chrome<\/th>\n<th>Safari<\/th>\n<\/tr>\n<tr>\n<td>1<\/td>\n<td>0.2494<\/td>\n<td>0.2489<\/td>\n<td>0.1612<\/td>\n<td>0.0947<\/td>\n<td>0.2458<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>0.2892<\/td>\n<td>0.2820<\/td>\n<td>0.1909<\/td>\n<td>0.1111<\/td>\n<td>0.1268<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td>0.2398<\/td>\n<td>0.2435<\/td>\n<td>0.2643<\/td>\n<td>0.1891<\/td>\n<td>0.0633<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>0.1628<\/td>\n<td>0.1638<\/td>\n<td>0.2632<\/td>\n<td>0.3779<\/td>\n<td>0.0323<\/td>\n<\/tr>\n<tr>\n<td>5<\/td>\n<td>0.0588<\/td>\n<td>0.0618<\/td>\n<td>0.1204<\/td>\n<td>0.2272<\/td>\n<td>0.5318<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>On Firefox, Internet Explorer is more frequently in one of the first 3 positions, while Safari is most often in last position.\u00a0 Strange.\u00a0 The same code, but vastly different results.<\/p>\n<p>The results here are also highly significant:<\/p>\n<pre>X-squared = 14831.41, df = 16, p-value &lt; 2.2e-16<\/pre>\n<p>So given the above, we know two things:\u00a0 1) The problem is real.\u00a0 2) The problem is not related to a flaw only in Internet Explorer.<\/p>\n<p>In the next section we look at the algorithm and show what the real problem is, and how to fix it.<\/p>\n<h3>Random shuffles<\/h3>\n<p>The browser choice screen requires what we call a &#8220;random shuffle&#8221;.\u00a0 You start with an array of values and return those same values, but in a randomized order. This computational problem has been known since the earliest days of computing.\u00a0 There are 4 well-known approaches: 2 good solutions, 1 acceptable (&#8220;good enough&#8221;) solution that is slower than necessary, and 1 bad approach that doesn&#8217;t really work.\u00a0 Microsoft appears to have picked the bad approach. But I do not believe there is some nefarious intent to this bug.\u00a0 It is more in the nature of a &#8220;naive&#8221; algorithm&#8221;, like the bubble sort, that inexperienced programmers\u00a0 inevitably will fall upon when solving a given problem.\u00a0 I bet if we gave this same problem to 100 freshmen computer science majors, at least one of them would make the same mistake.\u00a0 But with education and experience, one learns about these things.\u00a0 And one of the things one learns early on is to reach for <a href=\"http:\/\/www.amazon.com\/gp\/product\/0201896834\/ref=as_li_qf_sp_asin_il_tl?ie=UTF8&amp;tag=ananticdispos-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0201896834\">Knuth<\/a>.<\/p>\n<p><iframe style=\"width: 120px; height: 240px;\" src=\"\/\/ws-na.amazon-adsystem.com\/widgets\/q?ServiceVersion=20070822&amp;OneJS=1&amp;Operation=GetAdHtml&amp;MarketPlace=US&amp;source=ss&amp;ref=as_ss_li_til&amp;ad_type=product_link&amp;tracking_id=ananticdispos-20&amp;language=en_US&amp;marketplace=amazon&amp;region=US&amp;placement=0321751043&amp;asins=0321751043&amp;linkId=143a283920cd84ee6b51a55f582c0ca7&amp;show_border=true&amp;link_opens_in_new_window=true\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe><br \/>\n<cite>The Art of Computer Programming<\/cite>, Vol. 2, section 3.4.2 &#8220;Random sampling and shuffling&#8221; describes two solutions:<\/p>\n<ol>\n<li>If the number of items to sort is small, then simply put all possible orderings in a table and select one ordering at random.\u00a0 In our case, with 5 browsers, the table would need 5! = 120 rows.<\/li>\n<li>&#8220;Algorithm P&#8221; which Knuth attributes to Moses and Oakford (1963), but is now known to have been anticipated by Fisher and Yates (1938) so it is now called the <a href=\"http:\/\/en.wikipedia.org\/wiki\/Fisher-Yates_shuffle\">Fisher-Yates Shuffle<\/a>.<\/li>\n<\/ol>\n<p>Another solution, one I use when I need a random shuffle in a database or spreadsheet, is to add a new column, fill that column with random numbers and then sort by that column.\u00a0 This is very easy to implement in those environments. However, sorting is an O(N log N)\u00a0 operation where the Fisher-Yates algorithm is O(N), so you need to keep that in mind if performance is critical.<\/p>\n<p>Microsoft used none of these well-known solutions in their random solution.\u00a0 Instead they fell for the well-known trap.\u00a0 What they did is sort the array, but with a custom-defined comparison function or &#8220;comparator&#8221;.\u00a0 JavaScript, like many other programming languages, allows a custom comparator function to be specified.\u00a0 In the case of JavaScript, this function takes two indexes into the value array and returns a value which is:<\/p>\n<ul>\n<li>&lt;0 if the value at the first index should be sorted before the value at the second index<\/li>\n<li>0 if the values at the first index and the second index are equal, which is to say you are indifferent as to what order they are sorted<\/li>\n<li>&gt;0 if the value at the first index should be sorted after the value at the second index<\/li>\n<\/ul>\n<p>This is a very flexible approach, and allows the programmer to handle all sorts of sorting tasks, from making case-insensitive sorts to defining locale-specific collation orders, etc..<\/p>\n<p>In this case Microsoft gave the following comparison function:<\/p>\n<pre>function RandomSort (a,b)\r\n{\r\n    return (0.5 - Math.random());\r\n}<\/pre>\n<p>Since Math.random() should return a random number chosen uniformly between 0 and 1, the RandomSort() function will return a random value between -0.5 and 0.5.\u00a0 If you know anything about sorting, you can see the problem here.\u00a0 Sorting requires a self-consistent definition of ordering. The following assertions must be true if sorting is to make any sense at all:<\/p>\n<ol>\n<li>If a&lt;b then b&gt;a<\/li>\n<li>If a&gt;b then b&lt;a<\/li>\n<li>If a=b then b=a<\/li>\n<li>if a&lt;b and b&lt;c then a&lt;c<\/li>\n<li>If a&gt;b and b&gt;c then a&gt;c<\/li>\n<li>If a=b and b=c then a=c<\/li>\n<\/ol>\n<p>All of these statements are violated by the Microsoft comparison function.\u00a0 Since the comparison function returns random results, a sort routine that depends on any of these logical implications would receive inconsistent information regarding the progress of the sort.\u00a0 Given that, the fact that the results were non-random is hardly surprising.\u00a0 Depending on the exact search algorithm used, it may just do a few exchanges operations and then prematurely stop.\u00a0 Or, it could be worse.\u00a0 It could lead to an infinite loop.<\/p>\n<h3>Fixing the Microsoft Shuffle<\/h3>\n<p>The simplest approach is to adopt a well-known and respected algorithm like the Fisher-Yates Shuffle, which has been known since 1938.\u00a0 I tested with that algorithm, using a JavaScript implementation taken from the <a href=\"http:\/\/en.wikipedia.org\/wiki\/Fisher%E2%80%93Yates_shuffle\">Fisher-Yates<\/a> Wikpedia page, with the following results for 10,000 iterations in Internet Explorer:<\/p>\n<table border=\"1\">\n<caption>Internet Explorer raw counts<\/caption>\n<tbody>\n<tr>\n<th>Position<\/th>\n<th>I.E.<\/th>\n<th>Firefox<\/th>\n<th>Opera<\/th>\n<th>Chrome<\/th>\n<th>Safari<\/th>\n<\/tr>\n<tr>\n<td>1<\/td>\n<td>2023<\/td>\n<td>1996<\/td>\n<td>2007<\/td>\n<td>1944<\/td>\n<td>2030<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>1906<\/td>\n<td>2052<\/td>\n<td>1986<\/td>\n<td>2036<\/td>\n<td>2020<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td>2023<\/td>\n<td>1988<\/td>\n<td>1981<\/td>\n<td>1984<\/td>\n<td>2024<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>2065<\/td>\n<td>1985<\/td>\n<td>1934<\/td>\n<td>2019<\/td>\n<td>1997<\/td>\n<\/tr>\n<tr>\n<td>5<\/td>\n<td>1983<\/td>\n<td>1979<\/td>\n<td>2092<\/td>\n<td>2017<\/td>\n<td>1929<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table border=\"1\">\n<caption>Internet Explorer fraction of total<\/caption>\n<tbody>\n<tr>\n<th>Position<\/th>\n<th>I.E.<\/th>\n<th>Firefox<\/th>\n<th>Opera<\/th>\n<th>Chrome<\/th>\n<th>Safari<\/th>\n<\/tr>\n<tr>\n<td>1<\/td>\n<td>0.2023<\/td>\n<td>0.1996<\/td>\n<td>0.2007<\/td>\n<td>0.1944<\/td>\n<td>0.2030<\/td>\n<\/tr>\n<tr>\n<td>2<\/td>\n<td>0.1906<\/td>\n<td>0.2052<\/td>\n<td>0.1986<\/td>\n<td>0.2036<\/td>\n<td>0.2020<\/td>\n<\/tr>\n<tr>\n<td>3<\/td>\n<td>0.2023<\/td>\n<td>0.1988<\/td>\n<td>0.1981<\/td>\n<td>0.1984<\/td>\n<td>0.2024<\/td>\n<\/tr>\n<tr>\n<td>4<\/td>\n<td>0.2065<\/td>\n<td>0.1985<\/td>\n<td>0.1934<\/td>\n<td>0.2019<\/td>\n<td>0.1997<\/td>\n<\/tr>\n<tr>\n<td>5<\/td>\n<td>0.1983<\/td>\n<td>0.1979<\/td>\n<td>0.2092<\/td>\n<td>0.2017<\/td>\n<td>0.1929<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Applying Pearson&#8217;s Chi-square test we see:<\/p>\n<pre>X-squared = 21.814, df = 16, p-value = 0.1493<\/pre>\n<p>In other words, these results are not significantly different than a truly random distribution of positions.\u00a0 This is good.\u00a0 This is what we want to see.<\/p>\n<p>Here it is, in graphical form, to the same scale as the &#8220;Microsoft Shuffle&#8221; chart earlier:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" title=\"Fisher-Yates Shuffle\" src=\"https:\/\/2d823b65bb.nxcli.io\/blog\/attachments\/shuffle\/fisher-yates.png\" alt=\"\" width=\"628\" height=\"472\" \/><\/p>\n<h3>Summary<\/h3>\n<p>The lesson here is that getting randomness on a computer cannot be left to chance.\u00a0 You cannot just throw Math.random() at a problem and stir the pot, and expect good results.\u00a0 Random is not the same as being casual.\u00a0 Getting random results on a deterministic computer is one of the hardest things you can do with a computer and requires deliberate effort, including avoiding known traps.\u00a0 But it also requires testing.\u00a0 Where serious money is on the line, such as with online gambling sites, random number generators and shuffling algorithms are audited, tested and subject to inspection.\u00a0 I suspect that the stakes involved in the browser market are no less significant.\u00a0 Although I commend DSL.sk for finding this issue in the first place, I am astonished that the bug got as far as it did.\u00a0 This should have been caught far earlier, by Microsoft, before this ballot screen was ever made public.\u00a0 And if the EC is not already demanding a periodic audit of the aggregate browser presentation orderings, I think that would be a prudent thing to do.<\/p>\n<p>If anyone is interested, you can take a look at <a href=\"https:\/\/2d823b65bb.nxcli.io\/blog\/attachments\/shuffle\/shuffle.html\">the file I used for running the tests<\/a>.\u00a0 You type in an iteration count and press the execute button.\u00a0 After a (hopefully) short delay you will get a table of results, using the Microsoft Shuffle as well as the Fisher-Yates Shuffle.\u00a0 With 10,000 iterations you will get results in around 5 seconds.\u00a0 Since all execution is in the browser, use larger numbers at your own risk.\u00a0 At some large value you will presumably run out of memory, time out, hang, or otherwise get an unsatisfactory experience.<\/p>\n<div class=\"zemanta-pixie\" style=\"margin-top: 10px; height: 15px;\"><img decoding=\"async\" class=\"zemanta-pixie-img\" style=\"float: right;\" src=\"http:\/\/img.zemanta.com\/pixy.gif?x-id=4f53a829-1c7e-4a56-87c8-5fef3db7456d\" alt=\"\" \/><\/div>\n","protected":false},"excerpt":{"rendered":"<p>March 6th Update:\u00a0 Microsoft appears to have updated the www.browserchoice.eu website and corrected the error I describe in this post.\u00a0 More details on the fix can be found in The New &amp; Improved Microsoft Shuffle.\u00a0 However, I think you will still find the following analysis interesting. -Rob Introduction The story first hit in last week [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_genesis_hide_title":false,"_genesis_hide_breadcrumbs":false,"_genesis_hide_singular_image":false,"_genesis_hide_footer_widgets":false,"_genesis_custom_body_class":"","_genesis_custom_post_class":"","_genesis_layout":"","footnotes":""},"categories":[35,198],"tags":[194,192,191,195,193,196,197],"class_list":{"0":"post-766","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-microsoft","7":"category-popular","8":"tag-algorithm","9":"tag-chi-square-test","10":"tag-internet-explorer","11":"tag-javascript","12":"tag-random-number-generator","13":"tag-shuffling","14":"tag-statistics","15":"entry"},"_links":{"self":[{"href":"https:\/\/www.robweir.com\/blog\/wp-json\/wp\/v2\/posts\/766","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.robweir.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.robweir.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.robweir.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.robweir.com\/blog\/wp-json\/wp\/v2\/comments?post=766"}],"version-history":[{"count":42,"href":"https:\/\/www.robweir.com\/blog\/wp-json\/wp\/v2\/posts\/766\/revisions"}],"predecessor-version":[{"id":2678,"href":"https:\/\/www.robweir.com\/blog\/wp-json\/wp\/v2\/posts\/766\/revisions\/2678"}],"wp:attachment":[{"href":"https:\/\/www.robweir.com\/blog\/wp-json\/wp\/v2\/media?parent=766"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.robweir.com\/blog\/wp-json\/wp\/v2\/categories?post=766"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.robweir.com\/blog\/wp-json\/wp\/v2\/tags?post=766"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}