我有两个包含(解包)BCD号码的std :: deque对象。每个字节是一个BCD数字。尺寸不受限制,但MAX_SCALE = 10,因此1/3应该导致0.3333333333。对于这两个对象,将保存比例和符号:
class Numeric
{
std::deque<uint8_t> m_digits;
size_t m_scale; // indicates how many digits after "."
bool sign; // true = positive, false = negative
};
在计算之前将每个数值对象缩放为0,将10.34 / 2.1缩放为1034/210,并记录最高比例(2)以便稍后重新缩放。
将商计算到第三个数值对象的最快方法是什么?
我已经实现了加法,减法和乘法,但我找不到一个很好的解释如何实现(快速)divison(具有无限数量的数字)。
答案 0 :(得分:3)
您可以使用Newton的方法找到1 / a。
设f(x)= 1 / x - a,你想找到f ^ { - 1}(0)。
然后
x_{n + 1} = x_n - f(x_n) / f'(x_n)
收敛到f ^ { - 1}(0)。这给了我们
x_{n + 1} = x_n - (1 / x_n - a) / (-1 / x^2)
因此
x_{n + 1} = x_n * (2 - a * x_n)
收敛到1 / a。您使用标准
测试收敛if (|x_{n + 1} - x_n| < tolerance) then stop
你需要log n乘法来收敛。如果乘法是O(n ^ 2),则对于大数(O(n ^ 2),对O(n ^ 2 log n)),这比长除法慢。尽管如此,它实施起来很快,而且在实践中并没有那么糟糕。实际上,某些处理器使用此方案的变体来查找反转并执行分割。请注意,如果你有一个更好的乘法算法,那么Newton的方法优于渐近的长除法。
作为x_0的第一个猜测,您可以将除最高有效数字之外的所有数字设置为零,并直接找到它的反转。
示例:a = 3425,23。首先猜测:1 / a~1 / 3000~0.0033333333
另外,迭代
x_{n + 1} = x_n * (3 - a * x_n^2)
将收敛到1 / sqrt(a)(取两个前导数字和一个小的查找表进行初始猜测)。
答案 1 :(得分:0)
以整数算术执行所有操作:要计算10.34 / 2.1
,您要计算10340000000000 / 2100
,然后除以10^10
。要计算10340000000000 / 2100
,您只需要购买Knuth vol 2,就像Alexandre C已经提到过的那样。 (这不是你会后悔的事情!)我不认为牛顿的方法适用于此,除非你的数字非常大。