Echte Basisumwandlung

19

Wir hatten einige Herausforderungen bei der Basiskonvertierung, aber alle scheinen auf ganzzahlige Werte zuzutreffen. Lass es uns mit reellen Zahlen machen!

Die Herausforderung

Eingänge:

  • Eine echte positive Zahl x , ausgedrückt in Basis 10. Diese Zahl kann als Gleitkomma mit doppelter Genauigkeit oder als Zeichenfolge verwendet werden. Um Genauigkeitsprobleme zu vermeiden, kann davon ausgegangen werden, dass die Anzahl größer als 10 –6 und kleiner als 10 15 ist .
  • Eine Zielbasis b . Dies ist eine ganze Zahl von 2 bis 36.
  • Eine Anzahl von Nachkommastellen n . Dies ist eine ganze Zahl von 1 bis 20.

Ausgabe: Die Darstellung von x in der Basis b mit n Nachkommastellen.

Bei der Berechnung des Ausgabeausdrucks sollten die Ziffern nach dem n- ten abgeschnitten (nicht gerundet) werden. Zum Beispiel x = 3.141592653589793in base b = 3is 10.0102110122..., also für n = 3die Ausgabe wäre 10.010(Trunkierung), nicht 10.011(Rundung).

Für x und b , die eine endliche Anzahl von Stellen im Bruchteil ergeben, ist auch die entsprechende unendliche Darstellung (auf n Stellen gekürzt) zulässig. Beispielsweise kann 4.5dezimal auch dargestellt werden als 4.49999....

Sorgen Sie sich nicht um Gleitkommafehler .

Eingabe- und Ausgabeformat

x wird ohne führende Nullen angegeben. Wenn x zufällig eine Ganzzahl ist, können Sie davon ausgehen, dass sie mit einem Dezimalteil ( 3.0) oder ohne Dezimalteil ( 3) angegeben wird.

Die Ausgabe ist flexibel. Zum Beispiel kann es sein:

  • Ein String, der die Zahl mit einem geeigneten Trennzeichen (Dezimalpunkt) zwischen ganzzahligen und gebrochenen Teilen darstellt. Ziffern 11, 12usw. (für b über 10) als Buchstaben dargestellt werden A, Bwie üblich, oder wie andere eindeutige Zeichen (bitte angeben).
  • Eine Zeichenfolge für den ganzzahligen Teil und eine andere Zeichenfolge für den Bruchteil.
  • Zwei Arrays / Listen, eine für jeden Teil, die Zahlen von 0bis 35als Ziffern enthalten.

Die einzigen Einschränkungen bestehen darin, dass der ganzzahlige und der gebrochene Teil voneinander getrennt werden können (geeignetes Trennzeichen) und dasselbe Format verwenden (z. B. nein [5, 11]für die Liste, die den ganzzahligen Teil darstellt, und ['5', 'B']für die Liste, die den gebrochenen Teil darstellt).

Zusätzliche Regeln

Testfälle

Die Ausgabe wird als eine Zeichenfolge mit Ziffern dargestellt 0, ..., 9, A, ..., Zunter Verwendung .als Dezimal - Trennzeichen .

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
quelle
Lassen Sie uns diese Diskussion im Chat fortsetzen .
Erik der Outgolfer
für 42, 13, 1wir haben 33statt 33.0?
LiefdeWen
@LiefdeWen Nein, ein wesentlicher Teil der Herausforderung ist, dass die Ausgabe nDezimalstellen haben muss
Luis Mendo

Antworten:

1

Gelee , 16 Bytes

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

Probieren Sie es online!

Beachten Sie, dass Singletons als Element in der Ausgabe gedruckt werden.

Undichte Nonne
quelle
Hey, was ist mit deinem Bild passiert?
Luis Mendo
@ LuisMendo einige Leute können es nicht rendern, da es mit Facebook verbunden war
Leaky Nun
Du weißt, dass du hier ein Bild hochladen kannst, oder? Diese Standard sind so unpersönlich
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>

Funktioniert xzwischen 1e-6und 1e21, bvon 2bis 36(genau wie erforderlich) und nvon 1bis 10, 48abhängig von der Basis, bevor sich Gleitkommafehler einschleichen. Bearbeiten: 7 Bytes mit Hilfe von @Birjolaxew gespeichert. Weitere 3 Bytes mit Hilfe von @tsh gespeichert. Die vorherige 74-Byte-Version arbeitete auch mit negativen Zahlen:

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
quelle
1
Wie macht man eine Basiskonvertierung mit Regex?!?
Erik der Outgolfer
@EriktheOutgolfer bin ich nicht, es ist nur ein (hoffentlich) golferischer Weg, bis zu n"Ziffern" aus einer Zeichenfolge zu extrahieren .
Neil
Was ist dann die Kernlogik Ihrer Funktion?
Erik der Outgolfer
@EriktheOutgolfer Warum, die in JavaScript integrierte Basisumwandlungsfunktion natürlich. (Hinweis: Schauen Sie, wo ich den Basisparameter verwende.)
Neil
Oh, es heißt .toString(b)... dumm von mir> _ <
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

Hätte nicht gemerkt, dass ich die Ziffern einfach als Zahlen zurückgeben kann, das macht es viel einfacher. Gibt zwei Ziffernlisten zurück, die erste für den ganzzahligen Teil und die zweite für den Bruchteil.

Probieren Sie es online!

Arfie
quelle
Falls es hilft: Ich habe einen Hinweis hinzugefügt, dass Sie nur Nummern unterstützen müssen, die größer 1e-6(und kleiner als 1e15(wie zuvor)) sind
Luis Mendo,
5

Perl 6 , 25 Bytes

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

Versuch es

Erweitert:

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

Beachten Sie, dass das Leerzeichen so ist, dass es als (+x).base(b,n)
nicht analysiert wird +( x.base(b,n) ).

Brad Gilbert b2gills
quelle
Falls es hilft: Ich habe einen Hinweis hinzugefügt, dass Sie nur Nummern unterstützen müssen, die größer als 1e-6(und kleiner als 1e15, wie zuvor)
Luis Mendo
3

Mathematica, 158 Bytes

da diese herausforderung in mathematica von kelly powder bereits eine sehr gute antwort erhalten hat, habe ich versucht, (mit einem anderen ansatz) die exakten ergebnisse zu erzielen, die in den testfällen gezeigt werden

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


Eingang

[12944892982609, 29, 9]

Ausgabe

PPCGROCKS.000000000

J42161217
quelle
3

Ruby , 45 Bytes

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

Warum?

Da b ^ n in der Basis b 10 ^ n ist, multiplizieren wir x mit dieser Zahl und fügen dann den Dezimalpunkt hinzu, zu dem es gehört.

Probieren Sie es online!

GB
quelle
-1 Byte + Bugfix durch Ersetzen .rounddurch .to_i; Dies korrigiert die letzte Stelle der Ausgabe für diejenigen, bei denen sie nicht mit den Testausgaben übereinstimmt. -1 Byte mehr mit .insert ~n,?., ohne Klammer.
Nnnes
3

C (gcc) ,157 152 Bytes

Benötigt 64 Bit long intfür größere Testfälle.

-5 Bytes danke an 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;}}

Probieren Sie es online!

edit: ein paar bytes können rasiert werden, wenn zwei strings ausgegeben werden dürfen, die durch ein newline separator getrennt sind:

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: diese einsendung ist nicht die längste, yay!

scottinet
quelle
2
Sie können verwenden, printf(z+r)wenn es keine %Zeichen enthält. (Dies ist Code-Golf; Sicherheit und bewährte Verfahren gehen aus dem Fenster: P). Sie können auch verwenden puts(z+r), um eine neue Zeile kostenlos zu erhalten (Speichern der puts("")in der zweiten Version).
Peter Cordes
Vielen Dank! Ich habe vergessen, char * direkt als Muster anzugeben, das spart in der Tat einige Bytes :-) In der zweiten Version kann ich Puts (z + r) nicht verwenden, da dann jede Dezimalstelle in einer neuen
Zeile
Ah, dieser letzte Teil war ohne eine ungelöste Version mit Kommentaren nicht offensichtlich.
Peter Cordes
floatist kürzer als double, aber es scheint, dass die Frage eine doubleoder eine Zeichenfolge erfordert.
Peter Cordes
1
Keinen Bedarf. Einige gebräuchliche Implementierungen von C haben 64-Bit longund gemäß den Code-Golf-Regeln ist dies alles, was Sie brauchen, um eine gültige Antwort zu erhalten. (Es ist auch üblich, dass C- und C ++ - Code-Golf-Antworten 64-Bit annehmen long, da dies von Try It Online verwendet wird.) Ich empfehle, die Bearbeitung zurückzusetzen und nur eine Notiz wie " longmuss 64-Bit sein " hinzuzufügen dies, um die größeren Testfälle zu unterstützen. "
Peter Cordes
2

Mathematica 47 Bytes

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

RealDigitsZweimal aufrufen, um zuerst die Anzahl der Stellen links von der Dezimalstelle zu ermitteln.

Kelly Lowder
quelle
Falls es hilft: Ich habe eine Notiz hinzugefügt, dass Sie nur Zahlen unterstützen müssen, die größer als 1e-6(und kleiner als 1e15, wie zuvor)
Luis Mendo
1
Ich dachte, die Frage war nur gefragt TakeDrop@@RealDigits[##]& aber dann wurde mir klar, dass ich Dinge falsch verstanden habe - Ihre Lösung scheint optimal zu sein.
Mark S.
2

SageMath , 68 Bytes

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

Probieren Sie es online!

Uriel
quelle
Falls es hilft: Ich habe einen Hinweis hinzugefügt, dass Sie nur Nummern unterstützen müssen, die größer als 1e-6(und kleiner als 1e15, wie zuvor)
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]))

Probieren Sie es online!

g wandelt eine Zahl in eine Liste um, die diese Zahl in einer gegebenen Basis darstellt

zordnet ganze Zahlen Buchstaben zu ( 36 = .)

h Wendet die vorherigen Funktionen auf den ganzzahligen und den gebrochenen Teil einer Zahl an.

jferard
quelle
1

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

Diese Frage war besonders schwierig. Nach einiger Zeit in etwas schreiben, die richtigen Ergebnisse scheint es mit einem Makro für die Erhaltung der Ziffern () zu erzeugen ... es wird nicht zu viel Golf gespielt ... Ergebnisse:

(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

Das eigentliche Ziel ist eine Funktion, die jedes Float [mit k: = Ziffern ()] oder jede berechnete Zahl als% pi oder% e oder die Division von zwei float / int wie in 1./3 in Basis 2..36 umwandelt . ['oo' Ziffern]

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

Axiom, 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)

Ergebnisse

(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

Es hat ein kleines Problem für das letzte Null-Beispiel

 f(4.5,10,5)

Würde '4.5' und nicht '4.50000' zurückgeben

RosLuP
quelle