10 tabanından geçmeden herhangi bir tabandan herhangi bir tabana dönüşmenin ardındaki matematik mi?


35

Herhangi bir tabandan herhangi bir tabana dönüşmenin ardındaki matematiğe bakıyordum. Bu, sonuçlarımı her şeyden çok onaylamakla ilgili. Mathforum.org'daki cevabımın neye benzediğini buldum ama haklı olup olmadığımdan hala emin değilim. Daha büyük bir tabandan daha küçük bir tabana dönüşüm yapıyorum, çünkü sadece bir sonraki rakamı tekrarlamak istediğiniz ilk rakamı baz ile çarpın. Benim sorunum daha küçük bir tabandan daha büyük bir tabana geçişte ortaya çıkıyor. Bunu yaparken, istediğiniz daha büyük bir tabanı, sahip olduğunuz daha küçük bir tabana nasıl dönüştürmeniz gerektiği hakkında konuşurlar. Bir örnek, taban 4'ten taban 6'ya, 6 sayısını taban 4'e 12'ye dönüştürmeniz gerekir. Daha sonra, büyükten küçüğe çevirirken yaptığınız gibi yapın. Bununla ilgili zorluk, bir rakamın diğer tabanda ne olduğunu bilmenizin gerekmesi. Bu yüzden, 6'nın üs 4'te olduğunu bilmek zorundaydım. Bu, aklımda büyük bir sorun yaratıyor, çünkü o zaman bir masaya ihtiyacım olacaktı. Bunu daha iyi yapmanın bir yolunu bilen var mı?

Temel bir dönüşümün yardımcı olacağını düşündüm ama bu işi bulamadım. Ve siteden, 10 tabanından geçmeden tabandan tabana dönüşüm yapmanıza izin veriyor gibi gözüküyor ama ilk sayıyı tabandan tabana nasıl dönüştüreceğinizi bilmeniz gerekiyor. Bu biraz anlamsız kılıyor.

Yorum yapanlar bir mektubu sayıya dönüştürebileceğimi söylüyor. Eğer öyleyse bunu zaten biliyorum. Ancak bu benim sorunum değil. Benim sorunum, büyük bir tabanı küçük bir tabana dönüştürmek için önce sahip olduğum taban numarasını istediğim taban numarasına dönüştürmem gerekiyor. Bunu yaparken amacı yenerim çünkü bu üsleri başka üslere dönüştürebilirsem sorunumu zaten çözmüştüm.

Düzenleme: 10'dan küçük veya ona eşit tabanlardan 10'a eşit veya daha küçük diğer bazlara nasıl dönüştürüleceğini düşündüm. Sorun 10'dan büyük bir tabandan 10'dan büyük başka bir tabana dönüştürürken başlar veya 10'dan küçük bir tabandan 10'dan büyük bir tabana geçerken koda ihtiyacım yok. koda uygulanır.


1
Bu soru bu forum için mi?
Andrej Bauer 6'13

2
Hedef tabandaki toplama ve çarpma işlemlerini yapabildiğiniz sürece prosedür önemsizdir. Yapamazsan, bunun mümkün olduğunu sanmıyorum.
Karolis Juodel

9
Griffin'e önce birçok öğrencinin duyması gerekenler söylenmelidir: sayılar bir üssünde temsil edilmeden var olur . O zaman cevap açıktır: algoritmalara ihtiyacımız var: bir sayıdaki bir temsili verilen sayıyı sayıya dönüştürmek için algoritmalara ihtiyacımız var (yani, a stringve döndüren bir şey int) ve bir sayı alan ve gösterimini döndüren bir algoritma belirli bir tabanda.
Andrej Bauer 6'13

1
@AndrejBauer Soru CS ile ilgili: bu şekilde ifade edilmemiş olsa bile, bu sayı gösterimleri arasında dönüştürecek bir algoritma ile ilgili bir sorudur. [İlgisiz not: Bir sürü kafa karıştırıcı yorumu sildim. Griffin: Lütfen sorunuzu güncellemek için düzenleyin. Diğerleri: lütfen sohbete götür .]
Gilles 'ÇÖZME'

1
@Griffin, asıl sorunuzdan bu yana uzun zaman geçti. Umarım cevabını bulmuşsundur. Eğer öyleyse, bir cevabı güncellemek ve kabul etmek ya da sizinkileri göndermek iyi bir fikir olabilir. Bu arada, Google'ın Kod Sıkışma Arşivlerinde birkaç güzel fikir (C ++ 'da uygulama hakkında konuşmak) buldum. Bu sorunun bazı çözümleri çok yaratıcıdır code.google.com/codejam/contest/32003/dashboard
IsaacCisneros

Yanıtlar:


45

Bu bana çok temel bir soru gibi görünüyor, bu yüzden size biraz ders verdiğim için özür dilerim. Burada öğrenmeniz için en önemli nokta, bir sayının rakam gösterimi olmamasıdır . Sayı soyut bir matematiksel nesnedir, onun rakam gösterimi somut bir şeydir, yani bir kağıt üzerinde bir semboller dizisi (veya hesaplama belleğindeki bir bitler dizisi veya bir sayıyı ilettiğinizde yaptığınız bir sesler dizisi). Ne aklını karıştırıyor asla olmasıdır bkz bir sayı ama her zaman onun basamaklı temsilini. Yani numara olduğunu düşünerek sonuna kadar olan temsili.

Bu nedenle sorulması gereken doğru soru, "bir tabandan diğerine nasıl dönüştüğüm" değil, "hangi sayının belirli bir rakam dizesiyle temsil edildiğini nasıl bulabilirim" ve "bir rakamın gösterimini nasıl bulabilirim? verilen numara ".

Öyleyse Python'da bir sayı gösterimi sayıya çevirmek için diğeri işlevini yapmak için iki işlev üretelim. Not: Biz işlevini çalıştırdığınızda Python ders olacaktır ekranda baskı o tabanındaki 10'dan var Ama sayısı bu mu değil bilgisayar (ki değil) temel 10 sayı tutuyor anlamına gelir. Öyle ilgisiz bilgisayar sayılarını temsil eder nasıl.

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

Bunları test edelim:

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

Dönüştürme işlevleriyle donanmış sorununuz kolayca çözülür:

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

Bir test:

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

bc


4
b1b2b1b2

1
Soruyu sormak geçerlidir, ancak doğru cevabı bulmak, sayıların soyut varlıklar olduğunun farkında olmak en iyisidir.
Andrej Bauer

2
Bu yapar şekilde, taban 10 ile temsil sayısı geçen fromDigitstaban 10'da geri dönüş sayısı
apnorton

8
@anorton: Hayır, kesinlikle değil . Python, numarayı ekrandaki 10 basamaklı gösterimle basar, ancak sayının kendisi bu şekilde kaydedilmez. Karşı karşıya gelmeye çalıştığım, sayıların Python içinde nasıl uygulandığının önemsiz olduğu . Farketmez. Önemli olan tek şey, sayı gibi davranmalarıdır.
Andrej Bauer

3
Son olarak, herhangi bir baz için genel bir çözüm ve belirli kullanım durumlarıyla, 36'dan küçük bazlarla veya yeterli benzersiz sembollerle karşılaşabileceğiniz durumlar ile sınırlı değildir.
J.Money

21

Bunu anlamanın en iyi yolunun bir uzaylıyla (en azından analoji olarak) tartışılması olduğunu düşünüyorum.

xbx<b

Örnekler 10010011011 rakamlarının dizisi, 2 tabanındaki bir sayıdır, 68416841531 dizisi, 10 numaralı sayıdaki bir sayıdır, BADCAFE, 16 numaralı sayıdaki bir sayıdır.

qb

bbq

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

ϵs¯dd

bq

×+qq


0123456789XYZαβγδρζξ

Bu yüzden alfabenizi gördüm ve bunu şöyle sıraladım:

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

βξ

60Z8

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

βζ×βξ

Quux çarpım tablosu

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

βζ×βξ

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

bu yüzden bu kadar uzağa var

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

Şimdi daha önce belirtilen algoritmayı kullanarak eklemeyi yapmam gerekiyor:

δβγββδγδ

yani

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

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

qbq


1
Bu çok iyi dalgalı çizgiler oldu. Bilgisayarın bunu yapmasını nasıl sağlayabilirim?
Griffin

1
@Griffin, bence bu (garip) soruyu erken soruyorsun. Bir programlama dili seçer ve taban q numaralarına toplama ve çarpma algoritmasını yazarsınız (basamak listesi olarak gösterilir), ardından taban b basamaklarını taban q numaralarına yorumlamak ve taban b numaralarını taban q numaralarına yorumlamak için bir işlev tanımlayın. Bunları açıkladım.

Mesele şu ki, canlandırmaya çalıştığın kavramı biliyorum. Benim sorunum, bilgisayarım dalgalı çizgilerinizi kullanamıyor.
Griffin

Ne açıkladığını biliyorum ama uygulamaya koymak çok zor. Gördüğünüz rakamları tanımlamak o kadar kolay değil.
Griffin

1
Ayrıca alfa basamağını neden en anlamlı konuma düşürdünüz? 6'dan beri = & xi ;, 7 olmaz = & alpha; & alpha ;?
Giovanni Botta

9

Bu sadece bir üstlenmeden (Python 3) 'dir Andrej en kodu. Andrej'in kod numaraları bir basamak listesiyle (skalarlar) gösterilirken, aşağıdaki kod numaraları özel bir dizgeden alınan bir semboller listesiyle temsil edilir :

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)

Özel bir temelde değerden gösterime dönüşüm gerçekleştirmek için:

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

Temsilden (özel bir temelde) değere dönüşüm yapmak için:

>>> 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

Bir saklama tabanından diğerine bir temel dönüşüm gerçekleştirmek için:

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

1
Siteye hoşgeldiniz ve katkınız için teşekkürler. Ancak, iyi optimize edilmiş kaynak kodu üretmek bu sitenin gerçekte ne olduğu değildir. Andrej'in kodu kavramları açık bir şekilde ortaya koyuyor, bu onun cevabı için gerekli olan, ancak bunun ötesindeki kodu geliştirmek, bilgisayar bilimlerinden çok bir programlama meselesi .
David Richerby

1
@DavidRicherby Kısmen katılıyorum, ancak bu katkı bir yorum için çok uzun sürdü ve olması en iyi yer Andrej'in cevabına yakın bir yerdi, bu yüzden buraya gönderdim. Her neyse, daha iyi olduğunu düşünüyorsan, kodun bağlantısı olan bir yoruma çevirebilirim, ama fazladan bir saflık olmaz mıydı?
mmj

1

Temel dönüşüm işleminin temel işlemi toDigits()@AndrejBauer cevabının çalışmasıdır. Bununla birlikte, bunu yapmak için, sayıların iç gösteriminde, temel olarak taban 2 gösteriminden bir dönüşüm olan bir sayı oluşturmaya gerek yoktur. Gerekli işlemleri orijinal baz gösterimlerinde yapabilirsiniz.

Yani ilk adım tekrarlayan modulo bölünme işlemi yapmaktır

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

Dahili gösterim rakamlar olduğundan, sıfır test etmek için belirli bir fonksiyon yapmak gerekir.

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

Sonunda, aslında okulda öğrendiğimiz gibi varış yerine göre standart bölüm olan modulo_div işlemi gerçekleştirilmelidir.

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

sadece kodun doğru olduğunu doğrulayan bir test kontrolü yapın:

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]

Gönderdiğiniz için teşekkür ederiz, ancak bir kodlama sitesi olmadığımızı unutmayın, bu nedenle büyük bir kod bloğu burada bir cevap olarak uygun değildir. Özellikle de soru açıkça, “Koda ihtiyacım yok, sadece arkasındaki temel matematiğe ihtiyacım var” deyin.
David Richerby

@DavidRicherby Metin eklemeye çalıştım.
Xavier Combelle

Teşekkürler. Ve görüyorum ki, bu sayfada bir sürü kod var!
David Richerby

0

Bir bilgisayar programı gerektirmeyen temel dönüşüm yapmak için kolay bir yol biliyorum. Herhangi bir tabandan üs 2'ye dönüşümün bir yolunu tanımlamak ve bunun tersini yapmak ve sonra bir tabandan bir başkasına örtmek ilk önce ilk tabandan taban 2'ye dönüştürmek ve sonra taban 2'den diğer tabana dönüştürmek suretiyle gerçekleştirilir. 2 çarpmak veya herhangi bir tabanda bölmek çok kolaydır.

Herhangi bir tabandan taban 2'ye dönüştürmek için tek yapmanız gereken, herhangi bir sayı için, taban 2 notasyonunu alırsanız ve 0'dan başlayıp her basamak için soldan sağa iki sıra sırasına basarsanız, 1 rakamdan iki katına çıkarsa, bu rakam 1 ise, bu sayının kendisine gelir. Şimdi, bu sayıyı herhangi bir temelde verdiğinizde, bir bölüm ve geri kalanı elde etmek için o temelde 2'ye bölebilirsiniz. Kalan 1 ise, son ikili hane 1'dir ve geri kalan 0 ise, son ikili hane 0'dır. Yine 2'ye bölün. Kalan 1 ise, ikinci son hane 1'dir ve geri kalan 0 ise, ikinci son hane 0 olur ve 0 olanı alana kadar devam eder.

Taban 2'den herhangi bir tabana dönüştürmek için tek yapmanız gereken o tabanda, 0'dan başlamak, sonra soldan sağa doğru giden her ikilik basamak için, o basamakta iki katına, o basamak 0 ise iki kat ve 1 Bu rakam 1 ise temel.


2 is so easy to multiply or divide by in any base.İkiden birinin gücünden (11 ve 13 ile başlamak için) birden fazla olan tek bazlar için bunu görmüyorum.
greybeard

0

Baz n'den baz 10'a, bazı orta bazlara dönüşüm olmadan dönüştürebilirsiniz.

Baz n'den baz 9'a dönüştürmek için, örneğin, baz 10'a dönüşüm algoritmasını alırsınız ve “10” u “9” ile değiştirirsiniz. Başka bir üs için aynı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.