将一个大数(二进制,带有重复数字)转换为十进制。

huangapple go评论97阅读模式
英文:

Converting a BigNum (binary w/ repeating digits) to decimal

问题

我目前有一个基于有理数(带有重复数字)的大数实现,存储以下内容(以二进制表示):

  • 整数部分
  • 小数部分
  • 重复小数部分

一些示例(表示为<int>.<frac>(<repeating-frac>)):

  • 2.5(十进制):10.1(二进制)
  • 2.1(十进制):10.0(0011)(二进制)
  • 2.5(3)(十进制):10.(1000)(二进制)

我可以通过以下过程从十进制(或任何进制)转换为二进制(这是大数实际存储在磁盘上的方式):

  • 对于整数部分,简单地将其除以2(字符串除法),直到它为0为止。
    在这种情况下,每次除法后的余数编码了数字。

  • 对于小数部分,继续乘以2(字符串乘法),直到它为0或进入循环为止。

    • 如果变为0,我们只有小数部分而没有重复小数部分。
    • 如果进入循环,循环之前的所有数字进入小数部分,其余数字进入重复小数部分。

    无论哪种情况,乘法的“余数”/溢出编码了小数部分。

问题出现在从二进制转换为十进制(或任何其他进制)时。我目前的过程如下:

  • 通过反转过程并将所有数字的余数相加,乘以2并加上所有数字的余数,得到整数部分。

  • 通过添加“余数”/溢出并除以2,得到纯小数(非重复)部分。

然而,对于重复的小数部分,我不知道如何开始。当解码整数或纯小数时,我从值0开始,因为编码过程以值0结束。然而,对于重复小数部分,结束值不是0,所以我不能从0开始并期望得到相同的值。

我不想存储这个停止数字,因为我知道,例如,0.0(0011)(二进制)唯一且明确地映射到0.1(十进制)。任何数字组合都是如此。它们都应该映射到唯一的十进制(或任何其他进制)等价物。

鉴于此,我不想浪费空间存储结束值,因为必须有一种方法可以回到原始值。

那么,我怎么从二进制编码(带有重复数字)转换为基数N的编码(可能带有重复数字)?

如果通用基数不可能,我只对8、10和16进制感兴趣,其中8和16是微不足道的,因为它们是2的幂,所以我真正关心的只是从二进制转换为十进制。

英文:

I currently have a big-num implementation based on rational numbers (with repeating digits) that stores the following (in binary):

  • Integer part
  • Fraction part
  • Repeating fraction part

Some examples (Expressed as <int>.<frac>(<repeating-frac>)):

  • 2.5 (base 10): 10.1 (base 2)
  • 2.1 (base 10): 10.0(0011) (base 2)
  • 2.5(3) (base 10): 10.(1000) (base 2)

I can convert from base 10 (or any base) to base 2 (which is how the big-num is actually stored on disk) with the following procedure:

  • For the integer part, simply keep dividing it (string division) by 2 until it's 0.

    In this case, the remainders after each division encode the number.

  • For the fractional part, keep multiplying (string multiplication) by 2 until it's either 0, or in a loop.

    • If we get to 0, we only have a fraction part and no repeating fraction.
    • If we get into a loop, all digits before the loop go into the fraction part and all others into the repeating fraction part.

    In either case, the "remainder" / overflow of the multiplication encodes the fractional parts.

The problem arises when converting from base 2 to base 10 (or any other base). I have the following procedure currently:

  • Get the integer part fine by reversing the process and multiplying by 2 and adding the remainders of all digits.

  • Get the pure fractional (non-repeating) part by adding the "remainder" / overflow and dividing by 2

However, for the repeating fractional part, I'm at a loss on how to start. When decoding the integer or pure fractional, I start with the value at 0, since the encoding procedures end with the value at 0. However, for the repeating fractional part, the end value is not 0, so I can't start at 0 and expect to get the same value out.

I don't want to store this stop number because I know that, for e.g., 0.0(0011) (base 2) maps uniquely and unambiguously to 0.1 (base 10). The same is true of any digit combination. They should all map to a unique decimal (or any other base) equivalent.

Given this, I don't want to waste space storing the end value, since there must be a way to get back to the original value.

So how can I go from a base 2 encoding (with repeating digits) to a base N encoding (possibly with repeating digits)

If a generic base isn't possible, I'm only really interested in bases 8, 10 and 16, of which 8 and 16 are trivial, as they are powers of 2, so 10 is the only other base I really care about converting to from base 2.

答案1

得分: 0

以下是翻译好的部分:

事实证明,答案相对简单:我们只需执行与从基数N转换为基数2时相同的算法,但不是将基数N的字符串除以2,而是将基数2的字符串除以N。

以下是针对基数N的通用算法,与问题中的算法相同:

  • 对于整数部分,只需将其除以N,直到为0为止。

在这种情况下,每次除法后的余数编码了基数N中的数字。

  • 对于小数部分,继续乘以N,直到要么为0,要么进入循环。
    • 如果达到0,我们只有一个小数部分,没有重复的小数。
    • 如果进入循环,循环之前的所有数字都进入小数部分,其他数字都进入重复小数部分。

无论哪种情况,乘法的“余数”/溢出都编码了基数N中的小数部分。

现在,这确实会使实际实现变得复杂,因为通过2进行字符串除法/乘法比通过N进行二进制除法/乘法要简单得多,所以也许可以仅使用字符串操作来实现它,就像问题中的原始解码算法一样,适用于整数和非重复小数部分,但这可能需要比使用二进制操作更多的工作。

英文:

As it turns out, the answer was relatively simple: We simply need to perform the same algorithm as when converting from base N to base 2, but instead of dividing / multiplying a string of base N by 2, we instead divide / multiply a string of base 2 by N.

Here is the same algorithm as in the question, now generic for base N:

  • For the integer part, simply keep dividing it by N until it's 0.

    In this case, the remainders after each division encode the number in base N.

  • For the fractional part, keep multiplying by N until it's either 0, or in a loop.

    • If we get to 0, we only have a fraction part and no repeating fraction.
    • If we get into a loop, all digits before the loop go into the fraction part and all others into the repeating fraction part.

    In either case, the "remainder" / overflow of the multiplication encodes the fractional parts in base N.

Now this does complicate the actual implementation, as string division / multiplication by 2 is significantly easier than binary division / multiplication by N, so maybe it's possible to implement it using only string operations, as the original decoding algorithm in the question did for integers and non-repeating fractionals, but that would likely require a lot more work than using binary operations.

huangapple
  • 本文由 发表于 2023年4月20日 03:09:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76058055.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定