2

我编写了一个系统,能够将任何基数(2-36)转换为另一个整数基数,它可以将任何实数从基数 10 转换为任何其他基数(2-36)。

我的问题是将有理数/无理数从 10 以外的任何基数转换为另一个基数。

我使用以下算法进行小数点右侧的转换:

1) 取输入中小数点 (0.xxxxxx--->) 的右侧,并将其乘以要转换为的基数。

2)取大于一的数(点的左边),加到转换后的数的右边。

3)取乘积的右侧,在下一次重复中使用它作为乘数(它乘以基数)

4)重复直到满意或留下一个整数(右侧为0)。

这非常适合将任何浮点数从十进制转换为另一个基数,但显然您不能从非十进制的基数转换。

因此,我尝试将小数点右侧的初始值转换为以 10 为底,执行数学部分,然后在将其添加到输出值时将其转换回原始基数(之前已转换为新基数正在添加)。

不幸的是,这会返回小数点右侧的错误结果。因此,如果从不是以 10 为基数的基数转换,我的答案在左侧总是正确的,但在右侧是不正确的。

有没有人对如何使这项工作有任何想法?或者也许它不会?

编辑

或者,任何人都可以链接我/告诉我如何将有理的十六进制值转换为十进制吗?仅此一项就足以让我解决这个问题。

解决方案

对于将来阅读此问题的其他任何人,我发现了一个相当简单的解决此问题的方法。

您所要做的就是取小数点右侧的数字(无论它可能是什么基数)并将其转换为十进制(您可以在此处查看如何转换整数)。然后取该数字并除以其中的最大位值。例如:

A.C
C == 12 (dec)
12 / 16 = .75 (this is the fractional value in decimal)

然后,您可以获取该小数并通过我上面讨论的算法运行它。

感谢大家在这个问题上的帮助!

4

1 回答 1

3

使用浮点意味着您不想执行准确的计算。

只有以 2、4、8、16 为基数编写的数字才能准确地用 Java浮点值表示(考虑整数)。这是由于浮点表示的限制。

只有以 2, 4, 5, 8, 10, 16, 20, 25, 32,... 为基数的数字才能以十进制为基数准确打印。这是由于我们的十进制数系统的限制。

因此,我希望您应该调整一些关于结果舍入的规则,并在整个算法中实施这些规则。确保您舍入而不是截断,否则即使double类型的精度足以满足您的目的,或者可以准确表示数字,通过浮点数也会给您不正确的结果。

如果您想以更高的精度执行计算,请查看BigInteger该类并专门以整数重新设计您的算法。或者,使用来处理分数;这很有用,因为您的算法的输入总是可以准确地表示为分数。然而,最终它总是归结为定义结果舍入规则并正确实施它们。

编辑

  1. 正如我从评论中了解到的,您更喜欢在读取整个输入之前逐渐发出输出数字。这基本上是可能的,但是

    • 您需要保留一个区间,而不是单个数字,作为“累加器”;例如,如果到目前为止您已经阅读0.1111了三进制,那么您知道输出位于 and 之间0.493827160.50617284并且在此阶段您甚至无法发出小数点后的第一个十进制数字。这对于避免0.4999999992在最“理性”的输入上看到输出是必要的。

    • 当读取完整的输入时,“四舍五入”并根据区间的上限而不是下限发出输出更安全。三进制的这种方式0.1111将转换为十进制的 0.5。(如果您仅限于十六进制到十进制的转换,则可以忽略这一点。)

    • 跟踪输入达到的最大精度(间隔宽度的对数),并确保发出的输出数字不超过输入保证。

    • 使用可以安全处理所需的最大精度的区间端点(下限和上限)的内部表示。

    • 请记住,即使是非常流行的软件也偶尔会错误地了解该算法的细节,并避免在浮点数据类型中表示任何中间结果,或者将输入截断为可以安全表示的数字,如果它更长的话。

  2. 您在问题中提到了无理数,但是无论使用什么基数,可以用有限(或周期性重复)扩展表示的每个数字都是有理数。

  3. 在从十六进制到十进制的转换中,甚至可以始终准确地表示输出,这允许进行一些简化,例如无限期地等待下限和上限收敛。

于 2012-06-10T21:06:38.910 回答