我目前有一个基于有理数(带有重复数字)的大数实现,它存储以下内容(二进制):
一些例子(表示为
<int>.<frac>(<repeating-frac>)
):
2.5
(基数 10):10.1
(基数 2)2.1
(基数 10):10.0(0011)
(基数 2)2.5(3)
(基数 10):10.(1000)
(基数 2)我可以使用以下过程从基数 10(或任何基数)转换为基数 2(这是大数字实际存储在磁盘上的方式):
对于整数部分,只需将它(字符串除法)除以 2 直到它为 0。
在这种情况下,每次除法后的余数编码数字。
对于小数部分,继续乘以(字符串乘法)2,直到它为 0,或者在循环中。
无论哪种情况,乘法的“余数”/溢出都会对小数部分进行编码。
从基数 2 转换为基数 10(或任何其他基数)时会出现问题。我目前有以下程序:
通过反转过程并乘以 2 并添加所有数字的余数来获得整数部分。
通过添加“余数”/溢出并除以 2 得到纯小数(非重复)部分
然而,对于重复的小数部分,我不知道如何开始。在解码整数或纯小数时,我从0开始,因为编码过程以0结束。但是对于重复的小数部分,结束值不是0,所以我不能从0开始并期望获得相同的价值。
我不想存储这个停止号,因为我知道,例如,
0.0(0011)
(基数 2)唯一且明确地映射到 0.1
(基数 10)。任何数字组合也是如此。它们都应该映射到一个唯一的小数(或任何其他基数)等价物。
鉴于此,我不想浪费存储最终值的空间,因为必须有一种方法可以恢复到原始值。
那么我怎样才能从基数 2 编码(有重复数字)到基数 N 编码(可能有重复数字)
如果通用基数不可能,我只对基数 8、10 和 16 真正感兴趣,其中 8 和 16 是微不足道的,因为它们是 2 的幂,所以 10 是我真正关心的唯一其他基数转换为基数 2.
事实证明,答案相对简单:我们只需要执行与从基数 N 转换为基数 2 时相同的算法,但不是将基数 N 的字符串除以/乘以 2,而是将基数 N 的字符串除/乘以 2 N.
以 2 为底的字符串这是与问题中相同的算法,现在对基数 N 通用:
对于整数部分,简单地一直除以N直到它为0。
在这种情况下,每次除法后的余数编码以 N 为底的数字。
对于小数部分,一直乘以N直到它为0,或者在一个循环中。
无论哪种情况,乘法的“余数”/溢出都会对基数 N 中的小数部分进行编码。
现在这确实使实际实现变得复杂,因为字符串除以/乘以 2 比二进制除以/乘以 N 容易得多,所以也许可以仅使用字符串操作来实现它,就像问题中的原始解码算法对整数所做的那样和非重复小数,但这可能比使用二元运算需要更多的工作。