I've two std::deque objects containing (unpacked) BCD numbers. Each byte is one BCD digit. The size is not limited, but there is a MAX_SCALE = 10, so 1 / 3 should result in 0.3333333333. For both objects, the scale and sign is saved:
class Numeric
{
std::deque<uint8_t> m_digits;
size_t m_scale; // indicates how many digits after "."
bool sign; // true = positive, false = negative
};
Each Numeric object is scaled to 0 before calculation, 10.34 / 2.1 is scaled to 1034 / 210 and the highest scale (2) is recorded for rescale back later.
What is the fastest method to calculate the quotient into a third Numeric object?
I've already implemented addition, substraction und multiplication, but I can't find a good 开发者_如何学运维explanation how to implement (fast) divison (with an unlimited number of digits).
You can use Newton's method to find 1 / a.
Let f(x) = 1 / x - a, you want to find f^{-1}(0).
Then
x_{n + 1} = x_n - f(x_n) / f'(x_n)
converges to f^{-1}(0). This gives us
x_{n + 1} = x_n - (1 / x_n - a) / (-1 / x^2)
therefore
x_{n + 1} = x_n * (2 - a * x_n)
converges to 1 / a. You test convergence with the criterion
if (|x_{n + 1} - x_n| < tolerance) then stop
You roughly need log n multiplications to converge. If multiplications are O(n^2), this is slower than long division for large numbers (O(n^2), vs O(n^2 log n)). Nevertheless, it is quick to implement and not so bad in practice. In fact, some processors use a variant of this scheme to find inverses and perform divisions. Note that if you have a better multiplication algorithm, then Newton's method outperforms long division asymptotically.
As a first guess for x_0, you can set all but the most significant digit to zero, and find its inverse directly.
Example: a = 3425,23. First guess : 1 / a ~ 1 / 3000 ~ 0.0033333333
As an aside, the iteration
x_{n + 1} = x_n * (3 - a * x_n^2)
will converge to 1 / sqrt(a) (take two leading digits and a small lookup table for the initial guess).
Do everything in integer arithmetic: to calculate 10.34 / 2.1
, you want to calculate 10340000000000 / 2100
and then divide by 10^10
. And to calculate 10340000000000 / 2100
, you only need to purchase Knuth vol 2, as Alexandre C already mentioned. (This is not something that you will ever regret!) I don't think Newton's method is applicable here, unless your numbers are very large.
精彩评论