If you can sample uniformly from the real interval [0,1) then you can adjust your idea.
Sampling digit by digit uniformly does not work: If BASE=10, a = 1, and b = 13, then 75% of the numbers have first digit 0, and 25% have first digit 1.
75%: 01, 02, 03, 04, 05, 06, 07, 08, 09
25%: 10, 11, 12
However, if you use your method, 50% of generated numbers will have first digit 0 and 50% will have first digit 1.
However, this just tells you what distribution you need to sample from: the first digit is chosen from {0,1} with weights {75%, 25%}, and then the second digit is either chosen from {1,2,3,4,5,6,7,8,9} uniformly if the first digit was 0, otherwise from {0,1,2} uniformly.
So all you need to do is count how many numbers (as a percentage) have each first digit. Generally there are three cases: (1) first digit is smallest, so "a" matters, (2) first digit is largest, so "b" matters, (3) first digit is safely in the middle. (An actual implementation has to deal with the problem that (3) may not occur, and that both (1) and (2) can occur simultaneously, but these cases are easier to analyze.)
If you are ok with approximately uniform, then just use the difference (subtraction) of the leading digits to get an approximation of the ratio for use with your short PRNG.
If you need exactly uniform, then I think this idea just hides the problem in requiring a really good [0,1) PRNG. I suspect though that most uses are fine with the approximation (if you are using 32-bit PRNGs then the difference from uniform is less than 1/232).
If you need exactly uniform, then you can use the inefficient but unbiased and uniform method: generate all the digits uniformly at random from 0 to BASE. If the number lies in your range, return it. Otherwise, generate another. If you have a bignum-division, then you can use a modulo operation to speed this up in the same fashion as converting a 32-bit PRNG to a uniform distribution on {0,1,2,3,4,5,6,7,8,9}.
In more detail: Let C = B−A. Let n be the number of digits of C. Generate n random digits (each one uniformly from 0 to BASE−1 inclusive), and call this number D. If D is bigger than floor(BASEn/C)*C (so D is very large and near the top of the range), discard D and try again (or suffer some minor non-uniformity of size C/232). Otherwise, reduce D modulo C and add the result to A, that is return (D % C) + A.
For example, to sample exactly uniformly from {0,1,2,3,4,5,6,7,8,9} you cannot use a 32-bit PRNG and just take the result mod 10 since the resulting distribution is gives each of 0,1,2,3,4,5 weight 10.00000001% and 6,7,8,9 weight 9.999999986%. So what you do is ask the PRNG for a number D. If D ≤ 4294967290, then return D % 10, otherwise discard D and try again.
Again, for a lot of people these 0.00000001% deviations from uniform don't matter.
Why do we discard large D? Imagine we want to sample uniformly from {0,1,2,3,4}, but we only have a six-sided die. Our algorithm can be simple: roll the die and take the result mod 5. Unfortunately, we quickly see this is not uniform: We get 0 more than 33% of the time, while each of 1,2,3,4 occur less than 17% of the time. What went wrong?
We tried to use too much of the random number generator's range. The first 5 numbers are fine, but the next "5" numbers only had one number in it!
Imagine this algorithm instead: We roll the die. If the number is ≤ 5, then we return it mod 5, otherwise we roll again.
This returns each number exactly 20% of the time, but sometimes when we run the algorithm it takes a long time to return because it keeps re-rolling. The average number of rolls is 1.2, so its not too bad on average.
Ok, what if we have a 12-sided die? The correct algorithm is then: roll the die. If the number is ≤ 10, then return it mod 5, otherwise roll again. Again, this returns each of 0,1,2,3,4 exactly 20% of the time. The average number of rolls needed is still 1.2, so again not too bad on average.
We have the same problem generating our big random-numbers from 0 to C (exclusive). We need to leave out the "top-most" part of the random number generator, otherwise the generator will not be even. We can use any full multiple of C, but the "last" multiple of C, the one that is partial, we have to discard.