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


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.


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>


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!


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


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


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!


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


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.


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!


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.


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

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'

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.