Simulating the sum of random dice roll without a loop I want to perform a random roll of $n$ $k$-sided dice (with values $1$ to $k$), where only the sum of the consecutive rolls is the output I want to get. Assuming I have a (pseudo-)random number generator at hand, I can use a loop and just perform $n$ rolls and sum the result.
However, if the number of rolls grows, so does the time it takes to compute the result. Is there a way to simulate the result without breaking it down to individual rolls, with the same probability distribution of possible values?
 A: We know that the range of the sum s = X1 + X2 + ... + Xn is from n to  n*k. Now, we need to count the possible ways that we can write s = X1 + X2 + ... + Xn = c that n <= c <= n*k. As 1<= Xi <= k, we can rewrite the equation to s' = X1' + X2' + ... + Xn' = c - n such that 0 <= Xi' <= k-1 and Xi' = Xi - 1. Now, the number of possible ways that we can write s' = c-n is ((n + (c-n) - 1) choose n) = ((c-1) choose n) = (c-1)! / (n! * (c-n-1)!). Now, we have the discrete probability function of the sum for values c from n to n*k that is (c-1)! / (n! * (c-n-1)! * k^n) and for the others is zero (we have k^n because of the total possible combinations of values for X1 to Xn).
In sum, we reduced the problem into generating random values for the known probability distribution.
A: Considering approaches I found always seemed to scale in time or space requirements with respect to the number of rolls or the output range, approximating the distribution using the normal distribution, as Nick Reed suggested, might be sufficient for large values, if they are arbitrarily chosen.
I have used the Box–Muller transform to generate a number in the standard normal distribution, then scaled it accordingly with $\mu=\frac{nk+n}{2}$ and $\sigma^2=n\frac{(k-1)(k+1)}{12}$ based on the distribution of a random dice roll (the variance is the sum of the individual variances).
Here is a piece of code that uses this approach:
static readonly Random rnd = new Random();

static int DiceSim(int n, int k)
{
    if(n <= 40)
    {
        return DiceLoop(n, k); // for smaller values, using a loop is more accurate
    }else{
        return DiceNormal(n - 40, k) + DiceLoop(40, k); // in case the floating-point numbers get inaccurate, a number of "real" rolls can be added
    }
}

static int DiceLoop(int n, int k)
{
    int sum = n;
    for(int i = 0; i < n; i++)
    {
        sum += rnd.Next(k);
    }
    return sum;
}

static int DiceNormal(int n, int k)
{
    double s = Math.Sqrt(n * (k - 1) * (k + 1) / 12.0);
    double m = (n * k + n) / 2.0;
    double result;
    do{
        double r = Math.Sqrt(-2 * Math.Log(rnd.NextDouble()));
        double a = 2 * Math.PI * rnd.NextDouble();
        double sample = r * Math.Sin(a);
        result = Math.Round(sample * s + m);
    }while(result < n || result > n * k); // making sure an impossible result isn't generated
    return (int)result;
}

