Conversion de base réelle

19

Nous avons eu quelques défis pour la conversion de base, mais tous semblent s'appliquer aux valeurs entières. Faisons-le avec de vrais chiffres!

Le défi

Contributions:

  • Un vrai nombre x positif , exprimé en base 10. Il peut être pris comme un flottant double précision ou comme une chaîne. Pour éviter les problèmes de précision, le nombre peut être supposé supérieur à 10 −6 et inférieur à 10 15 .
  • Une base cible b . Ce sera un entier de 2 à 36.
  • Un certain nombre de chiffres fractionnaires n . Ce sera un entier de 1 à 20.

Sortie: la représentation de x dans la base b avec n chiffres fractionnaires.

Lors du calcul de l'expression de sortie, les chiffres au-delà du n -ième doivent être tronqués (non arrondis). Par exemple, x = 3.141592653589793dans la base b = 3est 10.0102110122..., donc pour n = 3la sortie serait 10.010(troncature), pas10.011 (arrondi).

Pour x et b qui produisent un nombre fini de chiffres dans la partie fractionnaire, la représentation infinie équivalente (tronquée à n chiffres) est également autorisée. Par exemple, 4.5en décimal peut également être représenté par 4.49999....

Ne vous inquiétez pas des erreurs en virgule flottante .

Format d'entrée et de sortie

x sera donné sans zéros de tête. Si x se trouve être un entier, vous pouvez supposer qu'il sera donné avec une partie décimale nulle ( 3.0), ou sans partie décimale (3 ).

La sortie est flexible. Par exemple, cela peut être:

  • Une chaîne représentant le nombre avec un séparateur approprié (point décimal) entre les parties entières et fractionnaires. Les chiffres 11, 12etc. (pour b au-delà de 10) peuvent être représentés par des lettres A,B comme d'habitude, ou comme tout autre caractère distinct (veuillez préciser).
  • Une chaîne pour la partie entière et une autre chaîne pour la partie fractionnaire.
  • Deux tableaux / listes, un pour chaque partie, contenant les nombres de 0à 35sous forme de chiffres.

Les seules restrictions sont que les parties entières et fractionnaires peuvent être différenciées (séparateur approprié) et utiliser le même format (par exemple, non [5, 11]pour la liste représentant la partie entière et['5', 'B'] pour la liste représentant la partie fractionnaire).

Règles supplémentaires

Cas de test

La sortie est disponible en tant que chaîne de chiffres 0, ..., 9, A, ..., Zen utilisant .comme séparateur décimal.

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
la source
Continuons cette discussion dans le chat .
Erik the Outgolfer
pour 42, 13, 1que nous pouvons avoir au 33lieu de 33.0?
LiefdeWen
@LiefdeWen Non, une partie essentielle du défi est que la sortie doit avoir ndes chiffres décimaux
Luis Mendo

Réponses:

1

Gelée , 16 octets

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

Essayez-le en ligne!

Notez que les singletons sont imprimés comme élément dans la sortie.

Leaky Nun
la source
Hé, qu'est-il arrivé à ta photo?
Luis Mendo
@LuisMendo certaines personnes ne peuvent pas le rendre, car il était connecté à Facebook
Leaky Nun
Vous savez que vous pouvez télécharger une photo ici, non? Ceux par défaut sont tellement impersonnels
Luis Mendo
7

JavaScript (ES8), 81 74 71 octets

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>

Fonctionne xentre 1e-6et 1e21, bde 2à 36(exactement comme requis) et nde 1à quoi que ce soit de 10à en 48fonction de la base avant que les erreurs à virgule flottante ne s'introduisent. Edit: 7 octets enregistrés avec l'aide de @Birjolaxew. Enregistré 3 octets supplémentaires avec l'aide de @tsh. La version précédente de 74 octets fonctionnait également avec des nombres négatifs:

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
la source
1
Comment faire une conversion de base avec regex?!?
Erik the Outgolfer
@EriktheOutgolfer Je ne le suis pas, c'est juste un moyen (espérons-le) golfeur d'extraire jusqu'à n"chiffres" d'une chaîne.
Neil
Alors quelle est la logique de base de votre fonction?
Erik the Outgolfer
@EriktheOutgolfer Pourquoi, la fonction de conversion de base intégrée de JavaScript bien sûr. (Astuce: regardez où j'utilise le paramètre de base.)
Neil
Oh ça dit .toString(b)... stupide moi> _ <
Erik le Outgolfer
5

Python 2 , 153 149 144 137 135 109 octets

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

Je n'avais pas remarqué que je pouvais simplement renvoyer les chiffres sous forme de nombres, ce qui le rend beaucoup plus simple. Renvoie deux listes de chiffres, la première pour la partie entière, la seconde pour le fractionnaire.

Essayez-le en ligne!

Arfie
la source
Au cas où cela aiderait: j'ai ajouté une note selon laquelle il vous suffit de prendre en charge des nombres supérieurs à 1e-6(et inférieurs à 1e15, comme précédemment)
Luis Mendo
5

Perl 6 , 25 octets

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

Essayez-le

Étendu:

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

Notez que l'espace est tel qu'il est analysé comme (+x).base(b,n)
non +( x.base(b,n) ).

Brad Gilbert b2gills
la source
Au cas où cela aiderait: j'ai ajouté une note selon laquelle il suffit de prendre en charge des nombres supérieurs à 1e-6(et inférieurs à 1e15, comme auparavant)
Luis Mendo
3

Mathematica, 158 octets

puisque ce défi a déjà obtenu une très bonne réponse en mathématique par @KellyLowder, j'ai essayé de produire (avec une approche différente) les résultats exacts comme indiqué dans les cas de test

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


contribution

[12944892982609, 29, 9]

production

PPCGROCKS.000000000

J42161217
la source
3

Rubis , 45 octets

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

Pourquoi?

Puisque b ^ n dans la base b est 10 ^ n, nous multiplions x par ce nombre, puis ajoutons la virgule décimale à laquelle il appartient.

Essayez-le en ligne!

GB
la source
-1 octet + correction de bogue en remplaçant .roundpar .to_i; cela corrige le dernier chiffre de la sortie pour ceux où il ne correspond pas aux sorties de test. -1 octet de plus en utilisant .insert ~n,?., sans parenthèses.
Nnnes
3

C (gcc) ,157 152 octets

Nécessite 64 bits long intpour que cela fonctionne avec des cas de test plus importants.

-5 octets grâce à 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;}}

Essayez-le en ligne!

edit: quelques octets peuvent être rasés s'il est autorisé à sortir deux chaînes séparées par un séparateur de nouvelle ligne:

149 octets:

#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: cette soumission n'est pas la plus longue, yay!

scottinet
la source
2
Vous pouvez l'utiliser printf(z+r)s'il ne contient aucun %caractère. (Il s'agit de code-golf; la sécurité et les bonnes pratiques sortent par la fenêtre: P). Vous pouvez également utiliser puts(z+r)pour obtenir une nouvelle ligne gratuitement (en l'enregistrant puts("")dans la deuxième version).
Peter Cordes
Merci! J'ai oublié de fournir un caractère * directement en tant que modèle, cela économise en effet pas mal d'octets :-) Je ne peux pas utiliser put (z + r) dans la deuxième version car cela signifierait que chaque décimale sera imprimée sur une nouvelle ligne
scottinet
Ah, cette dernière partie n'était pas évidente sans une version non golfée avec des commentaires.
Peter Cordes
floatest plus court que double, mais il semble que la question nécessite une doubleentrée ou une chaîne.
Peter Cordes
1
Pas besoin de çà. Certaines implémentations courantes de C ont 64 bits long, et selon les règles de code-golf, c'est tout ce dont vous avez besoin pour que votre réponse soit valide. (De plus, il est courant que les réponses de code-golf C et C ++ supposent 64 bits long, car c'est ce que Try It Online utilise.) Je suggère de revenir en arrière et de simplement ajouter une note comme " longdoit être 64 bits pour ceci pour soutenir les plus grands cas de test. "
Peter Cordes
2

Mathematica 47 octets

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

Appeler RealDigitsdeux fois pour déterminer le nombre de chiffres à gauche de la décimale.

Kelly Lowder
la source
Au cas où cela aiderait: j'ai ajouté une note selon laquelle vous devez uniquement prendre en charge des nombres supérieurs à 1e-6(et inférieurs à 1e15, comme auparavant)
Luis Mendo
1
Je pensais que la question demandait juste TakeDrop@@RealDigits[##]& mais j'ai réalisé que j'avais mal lu les choses - votre solution semble optimale.
Mark S.17
2

SageMath , 68 octets

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

Essayez-le en ligne!

Uriel
la source
Au cas où cela aiderait: j'ai ajouté une note selon laquelle il suffit de prendre en charge des nombres supérieurs à 1e-6(et inférieurs à 1e15, comme auparavant)
Luis Mendo
1

Haskell , 188 octets

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

Essayez-le en ligne!

g convertit un nombre en une liste représentant ce nombre dans une base donnée

zmappe les entiers aux lettres ( 36 = .)

h applique les fonctions précédentes à la partie entière et fractionnaire d'un nombre.

jferard
la source
1

Axiome, 566 octets

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

il était particulièrement difficile cette question; après quelque temps pour écrire quelque chose, les bons résultats semblent générer en utilisant une macro pour conserver les chiffres () ... ce n'est pas trop joué ... résultats:

(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

la cible réelle est une fonction qui se convertit en base 2..36 chaque Float [qui a k: = chiffres ()] ou chaque nombre calculé en% pi ou% e ou la division de deux float / int comme dans 1./3 . [chiffres «oo»]

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

Axiome, 127 octets

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)

résultats

(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

Il y a un petit problème pour l'exemple final zéro

 f(4.5,10,5)

Renverrait «4,5» et non «4,50000»

RosLuP
la source