Konversi basis nyata

19

Kami memiliki beberapa tantangan untuk konversi basis, tetapi semuanya tampaknya berlaku untuk nilai integer. Mari kita lakukan dengan bilangan real!

Tantangan

Input:

  • Angka positif x nyata , dinyatakan dalam basis 10. Ini dapat diambil sebagai pelampung presisi ganda atau sebagai string. Untuk menghindari masalah presisi, angka tersebut dapat dianggap lebih besar dari 10 −6 dan kurang dari 10 15 .
  • Sebuah basis sasaran b . Ini akan menjadi bilangan bulat dari 2 hingga 36.
  • Sejumlah digit fraksional n . Ini akan menjadi bilangan bulat dari 1 hingga 20.

Output: the representasi dari x dalam basis b dengan n pecahan digit.

Saat menghitung ekspresi output, digit di luar n -th harus dipotong (tidak dibulatkan). Misalnya, x = 3.141592653589793dalam basis b = 3adalah 10.0102110122..., jadi untuk n = 3output akan menjadi 10.010(pemotongan), bukan 10.011(pembulatan).

Untuk x dan b yang menghasilkan jumlah digit hingga dalam bagian fraksional, representasi tak hingga yang ekivalen (terpotong menjadi n digit) juga diperbolehkan. Misalnya, 4.5dalam desimal juga dapat direpresentasikan sebagai 4.49999....

Jangan khawatir tentang kesalahan floating point .

Format input dan output

x akan diberikan tanpa nol di depan. Jika x adalah bilangan bulat, Anda dapat mengasumsikan bahwa itu akan diberikan dengan bagian nol desimal ( 3.0), atau tanpa bagian desimal ( 3).

Outputnya fleksibel. Misalnya, itu bisa:

  • Sebuah string yang mewakili angka dengan pemisah yang cocok (titik desimal) antara bagian bilangan bulat dan pecahan. Digit 11, 12dll (untuk b di atas 10) dapat direpresentasikan sebagai huruf A, Bseperti biasa, atau sebagai karakter berbeda lainnya (harap sebutkan).
  • String untuk bagian integer dan string lain untuk bagian fraksional.
  • Dua array / daftar, satu untuk setiap bagian, berisi angka dari 0hingga 35sebagai digit.

Satu-satunya batasan adalah bagian integer dan fraksional dapat dipisahkan (pemisah yang sesuai) dan menggunakan format yang sama (misalnya, tidak [5, 11]untuk daftar yang mewakili bagian integer dan ['5', 'B']untuk daftar yang mewakili bagian fraksional).

Aturan tambahan

Uji kasus

Output ditampilkan sebagai string dengan angka 0, ..., 9, A, ..., Z, menggunakan .sebagai pemisah desimal.

x, b, n                    ->  output(s)

4.5, 10, 5                 ->  4.50000 or 4.49999
42, 13, 1                  ->  33.0 or 32.C
3.141592653589793, 3, 8    ->  10.01021101
3.141592653589793, 5, 10   ->  3.0323221430
1.234, 16, 12              ->  1.3BE76C8B4395
10.5, 2, 8                 ->  1010.10000000 or 1010.01111111
10.5, 3, 8                 ->  101.11111111
6.5817645, 20, 10          ->  6.BCE2680000 or 6.BCE267JJJJ
0.367879441171442, 25, 10  ->  0.94N2MGH7G8
12944892982609, 29, 9      ->  PPCGROCKS.000000000
Luis Mendo
sumber
Mari kita lanjutkan diskusi ini dalam obrolan .
Erik the Outgolfer
karena 42, 13, 1bisakah kita memiliki, 33bukan 33.0?
LiefdeWen
@LiefdeWen Tidak, bagian penting dari tantangan adalah bahwa output harus memiliki nangka desimal
Luis Mendo

Jawaban:

1

Jelly , 16 byte

*×⁵b⁸ḞðṖḣ⁹,ṫø⁹N‘

Cobalah online!

Perhatikan bahwa lajang dicetak sebagai elemen dalam output.

Biarawati Bocor
sumber
Hei, apa yang terjadi dengan fotomu?
Luis Mendo
@LuisMendo beberapa orang tidak dapat merendernya, karena terhubung ke Facebook
Leaky Nun
Anda tahu Anda dapat mengunggah gambar di sini, bukan? Yang standar itu sangat tidak pribadi
Luis Mendo
7

JavaScript (ES8), 81 74 71 byte

f=
(x,b,n,g=x=>x.toString(b))=>g(x-x%1)+'.'+g(x%1).substr(2,n).padEnd(n,0)
<div oninput=o.textContent=f(+x.value,b.value,n.value)><input id=x><input type=number min=2 max=36 value=10 id=b><input type=number min=1 max=20 value=10 id=n><pre id=o>

Berfungsi untuk xantara 1e-6dan 1e21, bdari 2ke 36(persis seperti yang diperlukan) dan ndari 1ke apa pun 10hingga 48bergantung pada basis sebelum kesalahan floating-point merayap masuk. Edit: Menyimpan 7 byte dengan bantuan dari @Birjolaxew. Menyimpan 3 byte lebih lanjut dengan bantuan dari @tsh. Versi 74 byte sebelumnya juga bekerja dengan angka negatif:

f=
(x,b,n,[i,d]=`${x.toString(b)}.`.split`.`)=>i+`.`+d.slice(0,n).padEnd(n,0)
<div oninput=o.textContent=f(+x.value,b.value,n.value)><input id=x><input type=number min=2 max=36 value=10 id=b><input type=number min=1 max=20 value=10 id=n><pre id=o>

Neil
sumber
1
Bagaimana cara melakukan konversi basis dengan regex?!?
Erik the Outgolfer
@EriktheOutgolfer Saya tidak, itu hanya cara golf (semoga) mengekstraksi hingga n"digit" dari string.
Neil
Lalu apa yang logika inti fungsi Anda?
Erik the Outgolfer
@EriktheOutgolfer Why, tentu saja fungsi konversi basis bawaan JavaScript. (Petunjuk: lihat di mana saya menggunakan parameter dasar.)
Neil
Oh katanya .toString(b)... bodoh saya> _ <
Erik the Outgolfer
5

Python 2 , 153 149 144 137 135 109 byte

def f(x,b,m):
 i=int(x);s=[];t=[]
 while i:s=[i%b]+s;i/=b
 while m:m-=1;x=x%1*b;t+=[int(x)]
 return s or[0],t

Tidak memperhatikan saya hanya bisa mengembalikan digit sebagai angka, sehingga membuatnya jauh lebih sederhana. Mengembalikan dua daftar digit, pertama untuk bagian integer, kedua untuk fraksional.

Cobalah online!

Arfie
sumber
Jika itu membantu: Saya telah menambahkan catatan bahwa Anda hanya perlu mendukung angka yang lebih besar dari 1e-6(dan kurang dari 1e15, seperti sebelumnya)
Luis Mendo
5

Perl 6 , 25 byte

->\x,\b,\n{+x .base(b,n)}

Cobalah

Diperluas:

-> \x, \b, \n {
  +x            # make sure it is a Numeric
  .base( b, n ) # do the base conversion
}

Perhatikan bahwa ruang sehingga parsing sebagai (+x).base(b,n)
tidak +( x.base(b,n) ).

Brad Gilbert b2gills
sumber
Jika itu membantu: Saya telah menambahkan catatan bahwa Anda hanya perlu mendukung angka yang lebih besar dari 1e-6(dan kurang dari 1e15, seperti sebelumnya)
Luis Mendo
3

Mathematica, 158 byte

karena tantangan ini sudah mendapat jawaban yang sangat bagus dalam mathatica oleh @KellyLowder, saya mencoba untuk menghasilkan (dengan pendekatan yang berbeda) hasil yang tepat seperti yang ditunjukkan dalam kasus uji

ToUpperCase[""<>Insert[StringReplace[ToString@BaseForm[#,p]&/@PadRight[#&@@(d=RealDigits[#,p=#2]),w=(#3+d[[2]])][[;;w]],"\n "<>ToString@p->""],".",d[[2]]+1]]&


memasukkan

[12944892982609, 29, 9]

keluaran

PPCGROCKS.000000000

J42161217
sumber
3

Ruby , 45 byte

->x,b,n{(x*b**n).round.to_s(b).insert(~n,?.)}

Mengapa?

Karena b ^ n dalam basis b adalah 10 ^ n, kita mengalikan x dengan angka itu, dan kemudian menambahkan titik desimal di mana ia berada.

Cobalah online!

GB
sumber
-1 byte + perbaikan bug dengan mengganti .rounddengan .to_i; ini memperbaiki digit terakhir dari output untuk yang tidak sesuai dengan output pengujian. -1 byte lebih banyak dengan menggunakan .insert ~n,?., tanpa tanda kurung.
Nnnes
3

C (gcc) ,157 152 byte

Perlu 64 bit long intuntuk ini agar bisa bekerja dengan case uji yang lebih besar

-5 byte terima kasih kepada Peter Cordes

#define P r=99;i=l=x;do{z[--r]=48+7*(l%b>9)+l%b;}while(l/=b);printf(z+r)
long i,r,l;char z[99];f(x,b,n)double x;{P;putchar(46);while(n--){x=(x-i)*b;P;}}

Cobalah online!

sunting: beberapa byte dapat dicukur jika diizinkan untuk menghasilkan dua string yang dipisahkan oleh pemisah baris baru:

149 byte:

#define P r=99;i=l=x;do{z[--r]=48+7*(l%b>9)+l%b;}while(l/=b);printf(z+r)
long i,r,l;char z[99];f(x,b,n)double x;{P;puts("");while(n--){x=(x-i)*b;P;}}

sunting: kiriman ini bukan yang terpanjang, yay!

scottinet
sumber
2
Anda dapat menggunakannya printf(z+r)jika tidak mengandung %karakter apa pun . (Ini adalah kode-golf; keamanan dan praktik-praktik baik keluar jendela: P). Anda juga dapat menggunakan puts(z+r)untuk mendapatkan baris baru secara gratis (menyimpan puts("")dalam versi kedua).
Peter Cordes
Terima kasih! Saya lupa tentang memberikan char * langsung sebagai pola, ini memang menghemat beberapa byte :-) Saya tidak dapat menggunakan put (z + r) dalam versi kedua karena itu berarti setiap desimal akan dicetak pada baris baru
scottinet
Ah, bagian terakhir itu tidak jelas tanpa versi tanpa komentar dengan komentar.
Peter Cordes
floatlebih pendek dari double, tetapi tampaknya pertanyaannya memang membutuhkan doubleinput string atau.
Peter Cordes
1
Tidak perlu untuk itu. Beberapa implementasi umum dari C memang memiliki 64-bit long, dan sesuai dengan aturan kode-golf itu saja yang Anda butuhkan agar jawaban Anda valid. (Juga, itu biasa untuk C dan C ++ jawaban kode-golf untuk mengasumsikan 64-bit long, karena itulah yang digunakan Try It Online.) Saya sarankan memutar kembali hasil edit Anda, dan hanya menambahkan catatan seperti " longharus 64-bit untuk ini untuk mendukung kasus uji yang lebih besar. "
Peter Cordes
2

Mathematica 47 Bytes

TakeDrop@@r[#,#2,#3+Last@(r=RealDigits)[#,#2]]&

Memanggil RealDigitsdua kali untuk pertama mengetahui angka digit di sebelah kiri desimal

Kelly Lowder
sumber
Jika itu membantu: Saya telah menambahkan catatan bahwa Anda hanya perlu mendukung angka yang lebih besar dari 1e-6(dan kurang dari 1e15, seperti sebelumnya)
Luis Mendo
1
Saya pikir pertanyaannya hanya menanyakan TakeDrop@@RealDigits[##]& tetapi kemudian saya menyadari bahwa saya telah salah membaca - solusi Anda tampaknya optimal.
Mark S.
2

SageMath , 68 byte

def f(n,b,k):y=n.str(b).split('.')+[''];return y[0],(y[1]+'0'*k)[:k]

Cobalah online!

Uriel
sumber
Jika itu membantu: Saya telah menambahkan catatan bahwa Anda hanya perlu mendukung angka yang lebih besar dari 1e-6(dan kurang dari 1e15, seperti sebelumnya)
Luis Mendo
1

Haskell , 188 byte

f=fromIntegral
g 0 _=[]
g n p=g(div n p)p++[mod n p]
z=(!!)(['0'..'9']++['A'..'Z']++['.'])
h x p l|(i,d)<-properFraction x=z<$>(g i p++[36]++(last$g(floor$d*(f p**f l))p:[0<$[1..l]|d==0]))

Cobalah online!

g mengonversi angka menjadi daftar yang menunjukkan angka itu di basis tertentu

zmemetakan bilangan bulat ke huruf ( 36 = .)

h menerapkan fungsi sebelumnya ke bagian bilangan bulat dan pecahan angka.

jferard
sumber
1

Aksioma, 566 byte

c:=alphanumeric()::List Character
f(a:INT,b:PI):List Character==(r:=[];repeat(y:=a rem b;r:=cons(c.(y+1),r);a:=a quo b;a=0=>break);r)
g(x)==floor(x)::INT
F(x)==>for i in 1..#x repeat z:=concat(z,x.i)
w(a:Float,b:PI,n:NNI):String==
  z:="";b<2 or b>36 or a<0=>z
  ip:=g(a);    fp:=g((a-ip)*b^n)
  ipb:=f(ip,b);fpb:=f(fp,b);cnt:=n-#fpb
  for i in 1..cnt repeat fpb:=cons(c.1,fpb)
  F(ipb);z:=concat(z,".");F(fpb)
  z

h(a,b,n)==>(n>=0 and b>0=>(nd123:=10+g(n*log_2(b)/log_2(10));mxv123456:=digits(nd123::PI);res78484:=w(a,b,n);digits(mxv123456);res78484);"")

pertanyaan ini sulit; setelah beberapa saat menulis sesuatu, hasil yang tepat tampaknya menghasilkan menggunakan satu makro untuk mempertahankan digit () ... itu tidak golf terlalu banyak ... hasil:

(7) -> h(4.5,10,5)
   (7)  "4.50000"
                                                             Type: String
(8) -> h(42,13,1)
   (8)  "33.0"
                                                             Type: String
(9) -> h(%pi,3,8)
   (9)  "10.01021101"
                                                             Type: String
(10) -> h(%pi,5,10)
   (10)  "3.0323221430"
                                                             Type: String
(11) -> h(1.234,16,12)
   (11)  "1.3BE76C8B4395"
                                                             Type: String
(12) -> h(0.367879441171442,25,10)
   (12)  "0.94N2MGH7G8"
                                                             Type: String
(13) -> h(12944892982609,29,9)
   (13)  "PPCGROCKS.000000000"
                                                             Type: String
(14) -> h(6.5817645,20,10)
   (14)  "6.BCE267JJJJ"
                                                             Type: String

target sebenarnya adalah satu fungsi yang dikonversi ke basis 2..36 setiap Float [yang memiliki k: = digit ()] atau setiap angka yang dihitung sebagai% pi atau% e atau pembagian dua float / int seperti pada 1./3 . ['oo' digit]

(15) -> h(%pi,13,800)
   (15)
  "3.1AC1049052A2C77369C0BB89CC9883278298358B370160306133CA5ACBA57614B65B410020
  C22B4C71457A955A5155B04A6CB6CC2C494843A8BBBBA9A039B77B34CB0C036CAC761129B3168
  B8BAB860134C419787C911812985646C7AAA3025BAA118B3AB8265CB347852065667291482145
  6C533447BC53A5262177C9985455C395626091A2CC3126B395C91B65B654A1804226197528410
  29A8A4A55CC7937B347B77B5A914127B11C6A57A84510775A9A467819A468B6B74339CC1290B2
  24921C6A771BC2AB6AB41735119C2231545A86399483119AAA5AC34B46B7B5C9089946A364860
  9B26CB0BAC0ABCBA182C12881933AA93C3942C71AA664753989A3C82166BA2109796C4A134607
  59725A72C9117AC980556A147557C319438287226C94725B125753B009387A48AA45CB1960A04
  A064052C00A6069371949872B14590895C555CB01A39B7589824B8621618A8B1971841201A2AB
  B04B80C7534CC1CB079581491995B46C679555316288C82665645A1A600C1A669B865651B6B842470C018B03C1115B3C4306C015C0B45C"
                                                             Type: String
RosLuP
sumber
1

Aksioma, 127 byte

g(a)==floor(a)::INT;f(a:Float,b:PI,n:NNI):Any==(b<2 or n>28=>%i;x:=g(a);radix(x,b)+radix(g((a-x)*b^n),b)::RadixExpansion b/b^n)

hasil

(4) -> f(%e,2,10)
   (4)  10.1011011111
                                                   Type: RadixExpansion 2
(5) -> f(%e,3,10)
   (5)  2.2011011212
                                                   Type: RadixExpansion 3
(6) -> f(%e,35,10)
   (6)  2.P4VBNEB51S
                                                  Type: RadixExpansion 35
(7) -> f(1.4,35,10)
   (7)  1.DYYYYYYYYY
                                                  Type: RadixExpansion 35
(8) -> f(%pi,3,8)
   (8)  10.01021101
                                                   Type: RadixExpansion 3
(9) -> f(%pi,5,10)
   (9)  3.032322143
                                                   Type: RadixExpansion 5
(10) -> f(1.234,16,12)
   (10)  1.3BE76C8B4395
                                                  Type: RadixExpansion 16

Ini memiliki sedikit masalah untuk contoh nol akhir

 f(4.5,10,5)

Akan kembali '4,5' dan bukan '4,50000'

RosLuP
sumber