Conversión de base real

19

Hemos tenido algunos desafíos para la conversión de bases, pero todos parecen aplicarse a valores enteros. ¡Hagámoslo con números reales!

El reto

Entradas:

  • Un número positivo real x , expresado en la base 10. Esto puede tomarse como un flotante de doble precisión o como una cadena. Para evitar problemas de precisión, se puede suponer que el número es mayor que 10 −6 y menor que 10 15 .
  • Una base objetivo b . Este será un número entero de 2 a 36.
  • Un número de dígitos fraccionarios n . Este será un entero del 1 al 20.

Salida: la representación de x en la base b con n dígitos fraccionarios.

Al calcular la expresión de salida, los dígitos más allá de la n -ésima se deben truncar (no redondear). Por ejemplo, x = 3.141592653589793en base b = 3es 10.0102110122..., por lo que para n = 3la salida sería 10.010(truncamiento), no 10.011(redondeo).

Para x y b que producen un número finito de dígitos en la parte fraccional, también se permite la representación infinita equivalente (truncada en n dígitos). Por ejemplo, 4.5en decimal también se puede representar como 4.49999....

No te preocupes por los errores de coma flotante .

Formato de entrada y salida.

x se dará sin ceros a la izquierda. Si x resulta ser un número entero, puede suponer que se dará con una parte decimal cero ( 3.0) o sin una parte decimal ( 3).

La salida es flexible. Por ejemplo, puede ser:

  • Una cadena que representa el número con un separador adecuado (punto decimal) entre partes enteras y fraccionarias. Los dígitos 11, 12etc. (para b más allá de 10) se pueden representar como letras A, Bcomo de costumbre, o como cualquier otro carácter distinto (especifique).
  • Una cadena para la parte entera y otra cadena para la parte fraccionaria.
  • Dos matrices / listas, una para cada parte, que contienen números de 0a 35como dígitos.

Las únicas restricciones son que las partes enteras y fraccionarias pueden separarse (separador adecuado) y usar el mismo formato (por ejemplo, no [5, 11]para la lista que representa la parte entera y ['5', 'B']para la lista que representa la parte fraccionaria).

Reglas adicionales

Casos de prueba

Salida se muestra como una cadena con dígitos 0, ..., 9, A, ..., Z, usando .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
fuente
Continuemos esta discusión en el chat .
Erik the Outgolfer
porque 42, 13, 1podemos tener en 33lugar de 33.0?
LiefdeWen
@LiefdeWen No, una parte esencial del desafío es que la salida debe tener ndígitos decimales
Luis Mendo

Respuestas:

1

Jalea , 16 bytes

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

Pruébalo en línea!

Tenga en cuenta que los singletons se imprimen como el elemento en la salida.

Monja permeable
fuente
Oye, ¿qué pasó con tu foto?
Luis Mendo
@LuisMendo algunas personas no pueden reproducirlo, ya que estaba conectado a Facebook
Leaky Nun
Sabes que puedes subir una foto aquí, ¿verdad? Los predeterminados son tan impersonales
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>

Funciona xentre 1e-6y 1e21, bdesde 2hasta 36(exactamente como se requiere) y ndesde 1cualquier cosa desde 10hasta 48dependiendo de la base antes de que los errores de punto flotante entren. Editar: Guardado 7 bytes con ayuda de @Birjolaxew. Se guardaron otros 3 bytes con la ayuda de @tsh. La versión anterior de 74 bytes también funcionaba con 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
fuente
1
¿Cómo se hace una conversión base con regex?!?
Erik the Outgolfer
@EriktheOutgolfer No lo soy, es solo una forma de golfista (con suerte) de extraer hasta n"dígitos" de una cadena.
Neil
Entonces, ¿cuál es la lógica central de su función?
Erik the Outgolfer
@EriktheOutgolfer Por qué, por supuesto, la función de conversión de base incorporada de JavaScript. (Sugerencia: mira dónde uso el parámetro base.)
Neil
Oh, dice .toString(b)... tonto> _ <
Erik the Outgolfer
5

Python 2 , 153 149 144 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

No me había dado cuenta de que puedo devolver los dígitos como números, por lo que es mucho más simple. Devuelve dos listas de dígitos, primero para la parte entera, segundo para la fracción.

Pruébalo en línea!

Arfie
fuente
En caso de que ayude: he agregado una nota que solo necesita admitir números mayores que 1e-6(y menores que 1e15, como antes)
Luis Mendo
5

Perl 6 , 25 bytes

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

Intentalo

Expandido:

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

Tenga en cuenta que el espacio es para que se analice como (+x).base(b,n)
no +( x.base(b,n) ).

Brad Gilbert b2gills
fuente
En caso de que ayude: he agregado una nota que solo necesita admitir números mayores que 1e-6(y menores que 1e15, como antes)
Luis Mendo
3

Mathematica, 158 bytes

Dado que este desafío ya obtuvo una respuesta muy buena en matemáticas por @KellyLowder, traté de producir (con un enfoque diferente) los resultados exactos como se muestra en los casos de prueba

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]

salida

PPCGROCKS.000000000

J42161217
fuente
3

Ruby , 45 bytes

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

¿Por qué?

Como b ^ n en la base b es 10 ^ n, multiplicamos x por ese número y luego sumamos el punto decimal al que pertenece.

Pruébalo en línea!

GB
fuente
-1 byte + corrección de errores reemplazando .roundcon .to_i; Esto corrige el último dígito de la salida para aquellos en los que no coincide con las salidas de prueba. -1 byte más usando .insert ~n,?., sin paréntesis.
Nnnes
3

C (gcc) ,157 152 bytes

Necesita 64 bits long intpara que esto funcione con casos de prueba más grandes.

-5 bytes gracias 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;}}

Pruébalo en línea!

editar: se pueden eliminar algunos bytes si se permite que salgan dos cadenas separadas por un separador de nueva línea:

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

editar: esta presentación no es la más larga, ¡yay!

scottinet
fuente
2
Puede usarlo printf(z+r)si no contiene ningún %carácter. (Esto es código golf; la seguridad y las buenas prácticas salen por la ventana: P). También puede usar puts(z+r)para obtener una nueva línea de forma gratuita (guardando puts("")en la segunda versión).
Peter Cordes
¡Gracias! Olvidé proporcionar un char * directamente como patrón, esto de hecho ahorra bastantes bytes :-) No puedo usar put (z + r) en la segunda versión ya que eso significaría que cada decimal se imprimirá en una nueva línea
scottinet
Ah, esa última parte no era obvia sin una versión no golfista con comentarios.
Peter Cordes
floates más corto que double, pero parece que la pregunta requiere una doubleentrada de cadena o.
Peter Cordes
1
No hay necesidad de eso. Algunas implementaciones comunes de C tienen 64 bits long, y de acuerdo con las reglas de código de golf, eso es todo lo que necesita para que su respuesta sea válida. (Además, es común que las respuestas de golf de código C y C ++ asuman 64 bits long, ya que eso es lo que utiliza Try It Online). Sugeriría revertir su edición, y simplemente agregar una nota como " longdebe ser de 64 bits para esto para apoyar los casos de prueba más grandes ".
Peter Cordes
2

Mathematica 47 Bytes

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

Llamar RealDigitsdos veces para averiguar primero el número de dígitos a la izquierda del decimal.

Kelly Lowder
fuente
En caso de que ayude: he agregado una nota que solo necesita admitir números mayores que 1e-6(y menores que 1e15, como antes)
Luis Mendo
1
Pensé que la pregunta era solo preguntar TakeDrop@@RealDigits[##]y luego me di cuenta de que había leído mal las cosas: su solución parece óptima.
Mark S.
2

SageMath , 68 bytes

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

Pruébalo en línea!

Uriel
fuente
En caso de que ayude: he agregado una nota que solo necesita admitir números mayores que 1e-6(y menores 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]))

Pruébalo en línea!

g convierte un número en una lista que representa ese número en una base dada

zasigna enteros a letras ( 36 = .)

h aplica las funciones anteriores al número entero y la parte fraccionaria de un número.

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

fue particularmente difícil esta pregunta; después de algún tiempo en escribir algo, los resultados correctos que parece generar usando una macro para preservar dígitos () ... no se juega demasiado al golf ... 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

el objetivo real es una función que convierte a base 2..36 cada Float [que tiene k: = dígitos ()] o cada número calculado como% pi o% e o la división de dos float / int como en 1./3 . ['oo' dígitos]

(15) -> h(%pi,13,800)
   (15)
  "3.1AC1049052A2C77369C0BB89CC9883278298358B370160306133CA5ACBA57614B65B410020
  C22B4C71457A955A5155B04A6CB6CC2C494843A8BBBBA9A039B77B34CB0C036CAC761129B3168
  B8BAB860134C419787C911812985646C7AAA3025BAA118B3AB8265CB347852065667291482145
  6C533447BC53A5262177C9985455C395626091A2CC3126B395C91B65B654A1804226197528410
  29A8A4A55CC7937B347B77B5A914127B11C6A57A84510775A9A467819A468B6B74339CC1290B2
  24921C6A771BC2AB6AB41735119C2231545A86399483119AAA5AC34B46B7B5C9089946A364860
  9B26CB0BAC0ABCBA182C12881933AA93C3942C71AA664753989A3C82166BA2109796C4A134607
  59725A72C9117AC980556A147557C319438287226C94725B125753B009387A48AA45CB1960A04
  A064052C00A6069371949872B14590895C555CB01A39B7589824B8621618A8B1971841201A2AB
  B04B80C7534CC1CB079581491995B46C679555316288C82665645A1A600C1A669B865651B6B842470C018B03C1115B3C4306C015C0B45C"
                                                             Type: String
RosLuP
fuente
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

Tiene un pequeño problema para el ejemplo final cero

 f(4.5,10,5)

Devuelve '4.5' y no '4.50000'

RosLuP
fuente