Conversão de base real

19

Tivemos alguns desafios para a conversão de base, mas todos parecem se aplicar a valores inteiros. Vamos fazer isso com números reais!

O desafio

Entradas:

  • Um número positivo real x , expresso na base 10. Isso pode ser tomado como um flutuador de precisão dupla ou como uma string. Para evitar problemas de precisão, o número pode ser considerado maior que 10 −6 e menor que 10 15 .
  • Uma base alvo b . Este será um número inteiro de 2 a 36.
  • Um número de dígitos fracionários n . Este será um número inteiro de 1 a 20.

Saída: a representação de x na base b com n dígitos fracionários.

Ao calcular a expressão de saída, os dígitos além do n- ésimo devem ser truncados (não arredondados). Por exemplo, x = 3.141592653589793em base b = 3é 10.0102110122..., portanto, para n = 3a saída seria 10.010(truncamento), não 10.011(arredondamento).

Para x e b que produzem um número finito de dígitos na parte fracionária, a representação infinita equivalente (truncada em n dígitos) também é permitida. Por exemplo, 4.5em decimal também pode ser representado como 4.49999....

Não se preocupe com erros de ponto flutuante .

Formato de entrada e saída

x será dado sem zeros à esquerda. Se x for um número inteiro, você pode assumir que ele será fornecido com uma parte decimal zero ( 3.0) ou sem parte decimal ( 3).

A saída é flexível. Por exemplo, pode ser:

  • Uma sequência que representa o número com um separador adequado (ponto decimal) entre partes inteiras e fracionárias. Dígitos 11, 12etc. (para b além de 10) podem ser representados como letras A, Bcomo de costume, ou como qualquer outro caractere distinto (especifique).
  • Uma sequência para a parte inteira e outra para a parte fracionária.
  • Duas matrizes / listas, uma para cada parte, contendo números de 0até 35como dígitos.

As únicas restrições são que as partes inteiras e fracionárias possam ser separadas (separador adequado) e usar o mesmo formato (por exemplo, não [5, 11]para a lista que representa a parte inteira e ['5', 'B']para a lista que representa a parte fracionária).

Regras adicionais

Casos de teste

Saída é mostrada como uma string com dígitos 0, ..., 9, A, ..., Z, utilizando .como separador decimal.

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
fonte
Vamos continuar esta discussão no chat .
Erik the Outgolfer
pois 42, 13, 1podemos ter em 33vez de 33.0?
Agradeço o seu contato
@LiefdeWen Não, uma parte essencial do desafio é que a saída deve ter ndígitos decimais
Luis Mendo

Respostas:

1

Gelatina , 16 bytes

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

Experimente online!

Observe que os singletons são impressos como o elemento na saída.

Freira Furada
fonte
Ei, o que aconteceu com sua foto?
Luis Mendo
@LuisMendo algumas pessoas não podem torná-lo, desde que foi conectado a Facebook
Leaky Nun
Você sabe que pode enviar uma foto aqui, certo? Aqueles padrão são tão impessoal
Luis Mendo
7

JavaScript (ES8), 81 74 71 bytes

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>

Obras de xentre 1e-6e 1e21, ba partir 2de 36(exatamente como necessário) e na partir 1de qualquer coisa, desde 10que 48dependendo da base antes de ponto flutuante erros fluência em Edit:. Saved 7 bytes com a ajuda de @Birjolaxew. Salvou mais 3 bytes com a ajuda de @tsh. A versão anterior de 74 bytes também funcionava com números negativos:

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
fonte
11
Como se faz a conversão base com o regex?!?
Erik the Outgolfer
@EriktheOutgolfer Eu não sou, é apenas uma maneira de extrair até n"dígitos" de uma string.
194 Neil
Então, qual é a lógica principal de sua função?
Erik the Outgolfer
@EriktheOutgolfer Ora, é claro, a função de conversão de base incorporada do JavaScript. (Dica: olhar para onde eu usar o parâmetro base.)
Neil
Ah, ele diz .toString(b)... me
mude
5

Python 2 , 153 149 144 137 137 135 109 bytes

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

Não havia notado que posso retornar os dígitos como números, o que torna muito mais simples. Retorna duas listas de dígitos, primeiro para a parte inteira, segundo para o fracionário.

Experimente online!

Arfie
fonte
Em caso de ajuda: Eu adicionei uma nota que você só precisa de números de suporte superiores 1e-6(e menos do que 1e15, como antes)
Luis Mendo
5

Perl 6 , 25 bytes

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

Tente

Expandido:

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

Observe que o espaço é analisado como (+x).base(b,n)
não +( x.base(b,n) ).

Brad Gilbert b2gills
fonte
Em caso de ajuda: Eu adicionei uma nota que você só precisa de números de suporte superiores 1e-6(e menos do que 1e15, como antes)
Luis Mendo
3

Mathematica, 158 bytes

Como esse desafio já obteve uma resposta muito boa no mathematica do @KellyLowder, tentei produzir (com uma abordagem diferente) os resultados exatos, como mostrado nos casos de teste

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


entrada

[12944892982609, 29, 9]

resultado

PPCGROCKS.000000000

J42161217
fonte
3

Ruby , 45 bytes

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

Por quê?

Como b ^ n na base b é 10 ^ n, multiplicamos x por esse número e adicionamos o ponto decimal ao qual ele pertence.

Experimente online!

GB
fonte
-1 byte + correção de bug substituindo .roundpor .to_i; isso corrige o último dígito da saída para aqueles em que não corresponde às saídas de teste. -1 byte a mais usando .insert ~n,?., sem parênteses.
Nnnes
3

C (gcc) ,157 152 bytes

Precisa de 64 bits long intpara que isso funcione com casos de teste maiores.

-5 bytes graças a 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;}}

Experimente online!

edit: alguns bytes podem ser raspados se for permitido gerar duas strings separadas por um separador de nova linha:

149 bytes:

#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;}}

edit: esta submissão não é a mais longa, sim!

escoteiro
fonte
2
Você pode usar printf(z+r)se não contiver nenhum %caractere. (Isso é código-golfe; a segurança e as boas práticas aparecem pela janela: P). Você também pode usar puts(z+r)para obter uma nova linha gratuitamente (salvando a puts("")na segunda versão).
Peter Cordes
Obrigado! Eu esqueci de fornecer um char * diretamente como um padrão, isso de fato economiza alguns bytes :-) Eu não posso usar puts (z + r) na segunda versão, pois isso significaria que cada decimal será impresso em uma nova linha
scottinet
Ah, essa última parte não era óbvia sem uma versão não destruída com comentários.
Peter Cordes
floaté menor que double, mas parece que a pergunta requer uma doubleentrada de string ou.
22416 Peter Cordes
11
Não é preciso isso. Algumas implementações comuns de C têm 64 bits longe, de acordo com as regras do code-golf, é tudo o que você precisa para que sua resposta seja válida. (Além disso, é comum que as respostas de golfe em código C e C ++ assumam 64 bits long, já que é isso que o Try It Online usa.) Sugiro reverter sua edição e adicionar uma nota como " longdeve ser de 64 bits para isso para dar suporte a casos de teste maiores ".
Peter Cordes
2

Mathematica 47 Bytes

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

Chamando RealDigitsduas vezes para descobrir primeiro o número de dígitos à esquerda do decimal.

Kelly Lowder
fonte
Em caso de ajuda: Eu adicionei uma nota que você só precisa de números de suporte superiores 1e-6(e menos do que 1e15, como antes)
Luis Mendo
11
Eu pensei que a pergunta estava apenas pedindo, TakeDrop@@RealDigits[##]mas então percebi que tinha interpretado mal as coisas - sua solução parece ótima.
Mark S.
2

SageMath , 68 bytes

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

Experimente online!

Uriel
fonte
Em caso de ajuda: Eu adicionei uma nota que você só precisa de números de suporte superiores 1e-6(e menos do que 1e15, como antes)
Luis Mendo
1

Haskell , 188 bytes

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

Experimente online!

g converte um número em uma lista que representa esse número em uma determinada base

zmapeia números inteiros para letras ( 36 = .)

h aplica as funções anteriores à parte inteira e fracionária de um número.

jferard
fonte
1

Axioma, 566 bytes

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);"")

foi particularmente difícil essa questão; depois de algum tempo escrevendo algo, os resultados certos parecem gerar usando uma macro para preservar dígitos () ... não é muito jogado ... resultados:

(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

o alvo real é uma função que converte na base 2..36 cada flutuador [que possui k: = dígitos ()] ou cada número calculado como% pi ou% e ou a divisão de dois flutuantes / int como em 1./3 . [dígitos oo]

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

Axioma, 127 bytes

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)

resultados

(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

Tem um pequeno problema para o exemplo final zero

 f(4.5,10,5)

Retornaria '4.5' e não '4.50000'

RosLuP
fonte