使用BCD格式的数字部门

时间:2011-06-27 20:29:50

标签: c++ numeric

我有两个包含(解包)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(具有无限数量的数字)。

2 个答案:

答案 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已经提到过的那样。 (这不是你会后悔的事情!)我不认为牛顿的方法适用于此,除非你的数字非常大。