从任何基数转换为任何基数而不经过基数10的背后的数学运算?


35

我一直在研究从任何基础转换为任何基础的数学运算。这比确认我的结果更重要。我在mathforum.org上找到了我的答案,但是我仍然不确定我是否正确。我可以从较大的基数转换为较小的基数,因为这只是将第一位数字乘以要添加下一位数字重复的基数即可。我的问题是从较小的基数转换为较大的基数时出现的。在执行此操作时,他们会讨论如何将所需的较大基准转换为较小的基准。一个例子是从4到6的基数,您需要将数字6转换为4到12的基数。然后执行与从大到小转换时相同的操作。我遇到的困难是,似乎您需要知道另一个数中的一个。因此,我需要知道4中的6是什么。这在我脑海中产生了一个大问题,因为那时我需要一个表。有谁知道以更好的方式做到这一点的方法。

我以为基本转换会有所帮助,但找不到任何有效的方法。从我发现的站点来看,它似乎允许您从基数转换为基数,而无需经过10底,但是您首先需要知道如何将第一个数字从基数转换为基数。这使得它毫无意义。

评论员说我需要能够将字母转换为数字。如果是这样,我已经知道了。但是那不是我的问题。我的问题是为了将大基数转换为小基数,我需要先将我拥有的基数转换为所需的基数。这样做我无法达到目的,因为如果我能够将这些碱基转换为其他碱基,那么我已经解决了我的问题。

编辑:我已经找到了如何从小于或等于10的基数转换为小于或等于10的其他基数的方法。我也可以从大于10的基数转换为小于等于10的任何基数。当从大于10的基数转换为大于10的基数时,或者从小于10的基数变为大于10的基数时,问题就开始了。我不需要代码,我只需要它后面的基本数学即可。适用于代码。


1
这个论坛的主题是这个问题吗?
Andrej Bauer

2
只要您可以在目标库中进行加法和乘法,该过程就很简单。如果不能,我认为不可能。
KarolisJuodelė2013年

9
首先应该告诉格里芬许多学生需要听什么:数字存在而没有基础。那么答案是明确的:我们需要的算法,一个用于convering一个表示在一个给定的基数的数字来编号(即,一些东西,需要string返回的int),以及一种算法,需要一个号码,返回其代表性在给定的基础上。
Andrej Bauer

1
@AndrejBauer这个问题是关于CS的:即使不是这样写的,这也是一个关于在数字表示之间转换的算法的问题。[无关的注解:我删除了一堆令人困惑的评论。格里芬:请编辑您的问题以进行更新。其他人:请带它聊天。]
吉尔斯(Gilles)'

1
@Griffin距您提出原始问题已有很长时间了。希望您找到了答案。如果是这样,更新和接受答案或发布您的答案可能是个好主意。同时,我在Google的Code Jam档案库中发现了几个非常好的想法(谈论C ++的实现)。解决此问题的一些方法非常有创意,例如code.google.com/codejam/contest/32003/dashboard
IsaacCisneros 2015年

Answers:


45

对我来说,这是一个非常基本的问题,对不起,请教一下。对您而言,最重要的一点是数字不是数字表示。数字是一个抽象的数学对象,而数字表示是一个具体的东西,即纸上的符号序列(或计算存储器中的位序列,或在传达数字时发出的声音序列)。令您感到困惑的是,您永远不会看到数字,而总是看到它的数字表示。因此,您最终认为数字表示形式。

因此,要问的正确问题不是“如何从一个基数转换为另一个基数”,而是“如何确定给定的数字串代表哪个数字”和“如何找到一个数字的数字表示形式”。给定的数字”。

因此,让我们在Python中产生两个函数,一个用于将数字表示形式转换为数字,另一个用于相反的功能。注:当我们运行功能的Python当然会在屏幕上打印它在底座10获得,但数量但这并不意味着计算机在基地10号保持(它不是)。这是不相关的电脑如何呈现的数字。

def toDigits(n, b):
    """Convert a positive number n to its digit representation in base b."""
    digits = []
    while n > 0:
        digits.insert(0, n % b)
        n  = n // b
    return digits

def fromDigits(digits, b):
    """Compute the number given by digits in base b."""
    n = 0
    for d in digits:
        n = b * n + d
    return n

让我们测试这些:

>>> toDigits(42, 2)
[1, 0, 1, 0, 1, 0]
>>> toDigits(42, 3)
[1, 1, 2, 0]
>>> fromDigits([1,1,2,0],3)
42

有了转换功能,您的问题很容易解决:

def convertBase(digits, b, c):
    """Convert the digits representation of a number from base b to base c."""
    return toDigits(fromDigits(digits, b), c)

一个测试:

>>> convertBase([1,1,2,0], 3, 2) 
[1, 0, 1, 0, 1, 0]

注意:我们通过基数10表示!我们将基本表示形式转换为数字,然后将数字转换为基本c。该数字没有任何形式。(实际上,计算机必须以某种方式表示它,并且确实使用芯片中发生的电信号和时髦的东西来表示它,但是肯定不是0和1。)bc


4
这不能说服我100%。实际上,您确实将数字转换为某种表示形式(尽管您可以声称不知道它是什么),因为计算机不是柏拉图式的数学家,并且您的算法无法将基数的任意数字序列转换为基数b 2;它只能转换具体机器可表示的序列。Python非常灵活。C不会那么宽容。询问如何将任意字符串从b 1转换为b 2是完全正确的;但是,只有在某些特定的碱基组合(例如2 <-> 16)时,这才可能在线性时间内实现b1b2b1b2
rici 2013年

1
提出问题是正确的,但是要找到正确的答案,最好知道数字是抽象实体这一事实。
Andrej Bauer

2
确实通过基座10表示通过的数量,作为fromDigits返回数以10为底数
apnorton

8
@anorton:不,最肯定它不是。Python在屏幕上以10位数字表示形式打印数字,但是数字本身不是用这种方式存储的。我试图了解的是,在Python中如何实现数字是无关紧要的。不要紧。唯一重要的是它们的行为类似于数字。
Andrej Bauer 2013年

3
最后,是针对任何基础的通用解决方案,并且不限于特定用例,小于36的基础或可以提供足够的唯一符号的实例。
J.Money 2015年

21

我认为理解这一点的最佳方法是与外星人进行讨论(至少作为一个类比)。

xbx<b

示例数字字符串10010011011是以2为底的数字,字符串68416841531是以10为底的数字,BADCAFE是以16为底的数字。

qb

bbq

[[ϵ]]=0[[s¯d]]=[[s¯]]×b+d

ϵs¯dd

bq

×+qq


0123456789XYZαβγδρζξ

因此,我已经看过您的字母并对其进行制表:

0α1β2γ3δ4ρ5ζ6ξ7βα8ββ9βγXβδYβρZβζ

βξ

60Z8

[[60Z8]]=ξ(βξ)3+α(βξ)2+βζ(βξ)+ββ

βζ×βξ

Quux乘法表

×βγδρζξββγδρζξγγρξβββδβζδδξβγβζγβγρρρβββζγγγξδδζζβδγβγξδρργξξβζγρδδργζββαβαγαδαραζαξα

βζ×βξ

βζ×βξξγρβζδβγγ

所以我已经走了这么远

[[60Z8]]=ξ(βξ)3+α(βξ)2+βζ(βξ)+ββ=ξ(βξ)3+α(βξ)2+δβγ+ββ

现在,我需要使用前面提到的算法来执行加法运算:

δβγββδγδ

所以

[[60Z8]]=ξ(βξ)3+α(βξ)2+βζ(βξ)+ββ=ξ(βξ)3+α(βξ)2+δβγ+ββ=ξ(βξ)3+α(βξ)2+δγδ

[[60Z8]]=ζδξγρ.

qbq


1
好吧,那是很多曲折的线条。我如何让计算机做到这一点?
格里芬

1
@格里芬,我想你是在提早(奇怪)这个问题。您选择一种编程语言,并输入用于对基数q(表示为数字列表)进行加法和乘法的算法,然后定义一个函数,以将基数b的数字解释为基数q的数字,并将基数b解释为基数q的数字。我已经解释了所有这一切。

我知道您要刻画的概念。我的问题是我的计算机无法使用弯曲的线条。
格里芬

我知道您的解释,但是将其付诸实践要困难得多。您会发现定义这些数字并不容易。
格里芬

1
另外,为什么将字母数字降到最重要的位置?由于6 =&xi ;,所以7 =&alpha;&alpha;吗?
Giovanni Botta 2014年

9

这只是Andrej代码的重构(Python 3)。在安德烈(Andrej)的代码中,数字是通过一列数字(标量)表示的,而在以下代码中,代码是通过从自定义字符串中提取的符号的列表来表示的:

def v2r(n, base): # value to representation
    """Convert a positive number to its digit representation in a custom base."""
    b = len(base)
    digits = ''
    while n > 0:
        digits = base[n % b] + digits
        n  = n // b
    return digits

def r2v(digits, base): # representation to value
    """Compute the number represented by string 'digits' in a custom base."""
    b = len(base)
    n = 0
    for d in digits:
        n = b * n + base[:b].index(d)
    return n

def b2b(digits, base1, base2):
    """Convert the digits representation of a number from base1 to base2."""
    return v2r(r2v(digits, base1), base2)

要在自定义基础中执行从值到表示的转换:

>>> v2r(64,'01')
'1000000'
>>> v2r(64,'XY')
'YXXXXXX'
>>> v2r(12340,'ZABCDEFGHI') # decimal base with custom symbols
'ABCDZ'

要将表示形式(自定义基础)转换为值,请执行以下操作:

>>> r2v('100','01')
4
>>> r2v('100','0123456789') # standard decimal base
100
>>> r2v('100','01_whatevr') # decimal base with custom symbols
100
>>> r2v('100','0123456789ABCDEF') # standard hexadecimal base
256
>>> r2v('100','01_whatevr-jklmn') # hexadecimal base with custom symbols
256

要从一个客户基础到另一个客户基础进行基本转换:

>>> b2b('1120','012','01')
'101010'
>>> b2b('100','01','0123456789')
'4'
>>> b2b('100','0123456789ABCDEF','01')
'100000000'

1
欢迎来到该网站,并感谢您的贡献。但是,生成经过优化的源代码并不是该网站真正要关注的。安德烈(Andrej)的代码使概念更清晰,这是他的答案所需要的,但是对代码的进一步改进则是编程问题,而不是计算机科学
大卫·里希比

1
@DavidRicherby我部分同意,但是此贡献太长了,无法发表评论,它的最佳位置就在Andrej的答案附近,这就是为什么我在这里张贴它。无论如何,如果您认为更好,我可以将其转换为带有代码链接的注释,但这不是纯粹主义吗?
mmj

1

基本转换的基本操作是toDigits()@AndrejBauer答案的操作。但是,要使其成为数字,则无需在数字的内部表示中创建数字,这基本上是从2到2的转换。您可以在原始基本表示形式中进行所需的操作。

所以第一步是做重复的模除运算

def convertBase(n,original_base,destination_base):
    digits = []    
    while not is_zero(n):
        digits.insert(0,modulo_div(n,original_base,destination_base))
    return digits

由于内部表示是数字,因此必须提供一种特定功能来测试零

def is_zero(n):
    for d in n:
        if d != 0:
            return False
    return True

最终,我们必须在学校学习到,实际上是对modulo_div进行标准的除法运算。

def modulo_div(n,original_base,destination_base):
    carry = 0
    for i in range(len(n)):
        d = n[i]
        d+=original_base*carry 
        carry = d%destination_base 
        d=(d//destination_base)
        n[i] = d
        #print(i,d,carry)
    return carry

只需进行测试以验证代码是否正确:

print(convertBase([1,1,2,0], 3, 2))
#[1, 0, 1, 0, 1, 0]

print(convertBase([1, 0, 1, 0, 1, 0], 2, 3))
#[1, 1, 2, 0]

感谢您的发布,但请注意,我们不是一个编码站点,因此此处的一大段代码不适合作为答案。尤其是当问题明确指出“我不需要代码时,我只需要它背后的基本数学”。
David Richerby

@DavidRicherby我尝试添加文本。
Xavier Combelle

谢谢。尽管我说了什么,但我发现此页面上有很多代码!
David Richerby

0

我知道进行基本转换的简单方法,不需要计算机程序。它是通过定义一种从任何基数转换为基数2的方法,反之亦然,然后先从第一个基数转换为基数2,再从基数2转换为另一基数,然后从一个基数转换为另一个基数。2很容易乘以或除以2。

要将任何基数转换为基数2,您所要做的就是识别任何数字,如果采用其基数2表示法,并从0开始,然后对于每个数字,则按从左到右的顺序按双精度顺序排列(如果该数字为零,如果该数字为1,则比加1加倍。现在给定任何基数的数字,您可以在该基数中除以2得到商和余数。如果余数为1,则最后一个二进制数字为1,如果余数为0,则最后一个二进制数字为0。再次除以2。如果余数为1,则倒数第二个数字为1,如果余数为0,则倒数第二个数字为0,依此类推,直到得到商0。

要将基数从2转换为任何基数,您所需要做的就是从该基数开始,从0开始,然后对于从左到右的每个二进制数字,如果该数字为0,则以该基数加倍,然后再加1如果该数字是1,则以底数为基础。


2 is so easy to multiply or divide by in any base.我看不到奇数基数大于2(以11和13开头)的任何幂。
灰胡子

0

您可以从n转换为10,而无需转换为任何中间基数。

例如,要从n转换为9,可以采用将算法转换为10的算法,然后将“ 10”替换为“ 9”。其他任何基地都一样。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.