Prawdziwa konwersja bazy

19

Mieliśmy kilka wyzwań związanych z konwersją podstawową, ale wszystkie wydają się mieć zastosowanie do wartości całkowitych. Zróbmy to z liczbami rzeczywistymi!

Wyzwanie

Wejścia:

  • Rzeczywista liczba dodatnia x , wyrażona w podstawie 10. Można to przyjąć jako zmiennoprzecinkowe podwójnej precyzji lub jako ciąg. Aby uniknąć problemów z precyzją, można założyć, że liczba ta jest większa niż 10 -6 i mniejsza niż 10 15 .
  • Podstawy cel b . Będzie to liczba całkowita od 2 do 36.
  • Liczbę ułamkową cyfr n . Będzie to liczba całkowita od 1 do 20.

Komunikat: przedstawienie z X bazy B, z n cyfr dziesiętnych.

Podczas obliczania wyrażenia wyjściowego cyfry poza n-tą powinny zostać obcięte (nie zaokrąglone). Na przykład x = 3.141592653589793w bazie b = 3jest 10.0102110122..., więc dla n = 3danych wyjściowych byłoby 10.010(obcięcie), a nie 10.011(zaokrąglenie).

Dla x i b, które tworzą skończoną liczbę cyfr w części ułamkowej, dozwolona jest również równoważna nieskończona reprezentacja (obcięta do n cyfr). Na przykład 4.5w systemie dziesiętnym można również przedstawić jako 4.49999....

Nie martw się błędami zmiennoprzecinkowymi .

Format wejściowy i wyjściowy

x będzie podane bez zer wiodących. Jeśli x jest liczbą całkowitą, możesz założyć, że zostanie podana z zerową częścią dziesiętną ( 3.0) lub bez części dziesiętnej ( 3).

Dane wyjściowe są elastyczne. Na przykład może to być:

  • Ciąg reprezentujący liczbę z odpowiednim separatorem (kropka dziesiętna) między częściami całkowitymi i ułamkowymi. Cyfry 11, 12etc (dla b poza 10) można przedstawić jako litery A, Bjak zwykle, lub jakichkolwiek innych wyraźnych znaków (proszę określić).
  • Ciąg dla części całkowitej i kolejny ciąg dla części ułamkowej.
  • Dwie tablice / listy, po jednej dla każdej części, zawierające liczby od 0do 35jako cyfry.

Jedynymi ograniczeniami są to, że części całkowite i ułamkowe można rozdzielić (odpowiedni separator) i użyć tego samego formatu (na przykład nie [5, 11]dla listy reprezentującej część całkowitą i ['5', 'B']dla listy reprezentującej część ułamkową).

Dodatkowe zasady

Przypadki testowe

Wyjście jest pokazany jako ciąg cyfr z 0, ..., 9, A, ..., Z, używając .jako separatora dziesiętnego.

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
źródło
Daj nam kontynuować tę dyskusję w czacie .
Erik the Outgolfer,
bo 42, 13, 1czy możemy 33zamiast tego 33.0?
LiefdeWen,
@LiefdeWen Nie, istotną częścią wyzwania jest to, że dane wyjściowe muszą mieć ncyfry dziesiętne
Luis Mendo

Odpowiedzi:

1

Galaretka , 16 bajtów

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

Wypróbuj online!

Zauważ, że singletony są drukowane jako element na wyjściu.

Leaky Nun
źródło
Hej, co się stało z twoim zdjęciem?
Luis Mendo,
@LuisMendo niektórzy ludzie nie mogą tego renderować, ponieważ był on połączony z Facebookiem
Leaky Nun
Wiesz, że możesz przesłać tutaj zdjęcie, prawda? Te domyślne są tak bezosobowe
Luis Mendo
7

JavaScript (ES8), 81 74 71 bajtów

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>

Działa xmiędzy 1e-6i 1e21, bod 2do 36(dokładnie tak, jak jest to wymagane) i nod 1do dowolnego od, 10w 48zależności od podstawy, zanim wkroczą błędy zmiennoprzecinkowe. Edytuj: Zapisano 7 bajtów przy pomocy @Birjolaxew. Zapisano kolejne 3 bajty z pomocą @tsh. Poprzednia 74-bajtowa wersja działała również z liczbami ujemnymi:

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
źródło
1
Jak zrobić podstawową konwersję z regex?!?
Erik the Outgolfer,
@EriktheOutgolfer Nie jestem, to tylko golfista (miejmy nadzieję) sposób na wyodrębnienie n„cyfr” z łańcucha.
Neil
Więc jaka jest podstawowa logika twojej funkcji?
Erik the Outgolfer,
@EriktheOutgolfer Dlaczego, oczywiście wbudowana podstawowa funkcja JavaScript do konwersji. (Wskazówka: spójrz na to, gdzie używam parametru podstawowego.)
Neil
Och, mówi .toString(b)... głupi mnie> _ <
Erik Outgolfer
5

Python 2 , 153 149 144 137 135 109 109 bajtów

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

Nie zauważyłem, że mogę po prostu zwrócić cyfry jako liczby, dzięki czemu jest to o wiele prostsze. Zwraca dwie listy cyfr, pierwsza dla części całkowitej, druga dla ułamka.

Wypróbuj online!

Arfie
źródło
Na wypadek, gdyby to pomogło: Dodałem notatkę, że potrzebujesz obsługiwać tylko liczby większe niż 1e-6(i mniejsze niż 1e15, jak poprzednio)
Luis Mendo
5

Perl 6 , 25 bajtów

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

Spróbuj

Rozszerzony:

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

Zauważ, że spacja jest tak przetworzona, że (+x).base(b,n)
nie +( x.base(b,n) ).

Brad Gilbert b2gills
źródło
Na wypadek, gdyby to pomogło: Dodałem notatkę, że potrzebujesz obsługiwać tylko liczby większe niż 1e-6(i mniejsze niż 1e15, jak poprzednio)
Luis Mendo
3

Mathematica, 158 bajtów

ponieważ to wyzwanie otrzymało już bardzo dobrą odpowiedź w matematyce autorstwa @KellyLowder, starałem się uzyskać (z innym podejściem) dokładne wyniki, jak pokazano w przypadkach testowych

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


Wejście

[12944892982609, 29, 9]

wynik

PPCGROCKS.000000000

J42161217
źródło
3

Rubinowy , 45 bajtów

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

Dlaczego?

Ponieważ b ^ n w podstawie b wynosi 10 ^ n, mnożymy x przez tę liczbę, a następnie dodajemy przecinek dziesiętny, do którego należy.

Wypróbuj online!

GB
źródło
-1 bajt + poprawkowe zastępując .roundw .to_i; naprawia to ostatnią cyfrę wyjścia, dla tych, które nie pasują do wyników testu. -1 więcej bajtów przy użyciu .insert ~n,?., bez nawiasów.
Nnnes
3

C (gcc) ,157 152 bajty

Potrzebuje 64 bitów, long intaby działało to z większymi przypadkami testowymi.

-5 bajtów dzięki Peterowi Cordesowi

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

Wypróbuj online!

edycja: kilka bajtów można ogolić, jeśli można wypisać dwa ciągi znaków oddzielone separatorem nowego wiersza:

149 bajtów:

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

edycja: to zgłoszenie nie jest najdłuższe, tak!

szkocki
źródło
2
Możesz użyć, printf(z+r)jeśli nie zawiera żadnych %znaków. (To jest kod-golf; bezpieczeństwo i dobre praktyki wychodzą przez okno: P). Możesz także użyć, puts(z+r)aby uzyskać nowy wiersz za darmo (zapisując puts("")w drugiej wersji).
Peter Cordes,
Dzięki! Zapomniałem o podaniu char * bezpośrednio jako wzorca, to rzeczywiście oszczędza sporo bajtów :-) Nie mogę używać putów (z + r) w drugiej wersji, ponieważ oznaczałoby to, że każdy przecinek będzie drukowany na nowej linii
scottinet
Ach, ta ostatnia część nie byłaby oczywista bez niepoznanej wersji z komentarzami.
Peter Cordes
floatjest krótszy niż double, ale wydaje się, że pytanie wymaga wprowadzenia doubleciągu lub łańcucha.
Peter Cordes
1
Nie ma takiej potrzeby. Niektóre popularne implementacje języka C mają 64-bit longi zgodnie z regułami golfa to wszystko, czego potrzebujesz, aby odpowiedź była poprawna. (Poza tym odpowiedzi C-C ++ w golfa kodowego są typowe dla wersji 64-bitowej long, ponieważ tego właśnie używa Try It Online.) Sugeruję wycofanie edycji i dodanie uwagi typu „ longmusi być 64-bitowy dla obsługuje to większe przypadki testowe ”.
Peter Cordes,
2

Mathematica 47 bajtów

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

RealDigitsDwukrotne wywołanie w celu ustalenia liczby cyfr po lewej stronie dziesiętnej.

Kelly Lowder
źródło
Na wypadek, gdyby to pomogło: Dodałem notatkę, że potrzebujesz obsługiwać tylko liczby większe niż 1e-6(i mniejsze niż 1e15, jak poprzednio)
Luis Mendo
1
Myślałem, że pytanie tylko mnie pyta, TakeDrop@@RealDigits[##]ale potem zdałem sobie sprawę, że źle odczytałem - Twoje rozwiązanie wydaje się optymalne.
Mark S.
2

SageMath , 68 bajtów

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

Wypróbuj online!

Uriel
źródło
Na wypadek, gdyby to pomogło: Dodałem notatkę, że potrzebujesz obsługiwać tylko liczby większe niż 1e-6(i mniejsze niż 1e15, jak poprzednio)
Luis Mendo
1

Haskell , 188 bajtów

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

Wypróbuj online!

g konwertuje liczbę na listę reprezentującą ten numer w danej bazie

zmapuje liczby całkowite na litery ( 36 = .)

h stosuje poprzednie funkcje do liczby całkowitej i części ułamkowej liczby.

Jferard
źródło
1

Aksjomat, 566 bajtów

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

to pytanie było szczególnie trudne; po pewnym czasie coś napisać, wydaje się, że właściwe wyniki generują za pomocą jednego makra dla zachowania cyfr () ... to nie jest zbyt gra w golfa ... wyniki:

(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

prawdziwym celem jest jedna funkcja, która konwertuje do podstawy 2..36 każdy zmiennoprzecinkowy [który ma k: = cyfry ()] lub każdą obliczoną liczbę jako% pi lub% e lub podział dwóch zmiennoprzecinkowych / int jak w 1./3 . [cyfry „oo”]

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

Aksjomat, 127 bajtów

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)

wyniki

(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

Ma mały problem z końcowym przykładem zerowym

 f(4.5,10,5)

Zwróciłby „4.5”, a nie „4.50000”

RosLuP
źródło