Well the .NET random is bad.

It seems really the problem is twofold: the reference is from 1992 and cites a 1981 publication's reference to an unpublished 1958 generator. Not to say that being old makes the algorithm bad, but it's a bad implementation of an algorithm that already is questionable given more recent research.

I'll go section by section: > //Apparently the range [1..55] is special (Knuth) and so we're wasting the 0'th position.

This is a silly comment. Knuth explicitly states that "24 and 55 in this definition were not chosen at random; they are special values that happen to define a sequence whose least significant bits, {Xn mod 2), will have a period of length 2^55 - 1. Therefore the sequence (Xn) must have a period at least this long."

Then you have the initial seeding of the LCG with with a = 21 and m = 55, which is interesting. Numerical Recipes uses those values, but Knuth whom they got the algorithm from does not suggest them. The closest Knuth suggests is 24 and 55. This suggestion is from 1981, so the viability is questionable (and Knuth clearly states that this is an unpublished algorithm from 1958 - Numerical Recipes itself questions the quality).

Then they use 21 for inextp - this is wrong. Numerical Recipes uses 31, and that is significant per the period length quote above. The use of 21 should measurable lower the period.

Instead if it were a simple LCG using values found in L'Ecuyer's 1999 publication on the topic (https://www.ams.org/journals/mcom/1999-68-225/S0025-5718-99-...) I assume it would have a better distribution.

So the implementation is a questionable algorithm from 1958, and it's done incorrectly. Numerical Recipes opens the chapter on randomness almost immediately with: "Now our first ... lesson in this chapter is: be very, very suspicious of a system-supplied rand()," and then the authors of the .NET random package show exactly why that is.