# Real base conversion

We've had a few challenges for base conversion, but all of them seem to apply to integer values. Let's do it with real numbers!

# The challenge

Inputs:

• A real positive number x, expressed in base 10. This can be taken as a double-precision float or as a string. To avoid precision issues, the number can be assumed to be greater than 10−6 and less than 1015.
• A target base b. This will be an integer from 2 to 36.
• A number of fractional digits n. This will be an integer from 1 to 20.

Output: the representation of x in base b with n fractional digits.

When computing the output expression, the digits beyond the n-th should be truncated (not rounded). For example, x = 3.141592653589793 in base b = 3 is 10.0102110122..., so for n = 3 the output would be 10.010 (truncation), not 10.011 (rounding).

For x and b that produce a finite number of digits in the fractional part, the equivalent infinite representation (truncated to n digits) is also allowed. For example, 4.5 in decimal can also be represented as 4.49999....

Don't worry about floating point errors.

# Input and output format

x will be given without leading zeros. If x happens to be an integer you can assume that it will be given with a zero decimal part (3.0), or without decimal part (3).

The output is flexible. For example, it can be:

• A string representing the number with a suitable separator (decimal point) between integer and fractional parts. Digits 11, 12 etc (for b beyond 10) can be represented as letters A, B as usual, or as any other distinct characters (please specify).
• A string for the integer part and another string for the fractional part.
• Two arrays/lists, one for each part, containing numbers from 0 to 35 as digits.

The only restrictions are that the integer and fractional parts can be told apart (suitable separator) and use the same format (for example, no [5, 11] for the list representing the integer part and ['5', 'B'] for the list representing the fractional part).

# Test cases

Output is shown as a string with digits 0, ..., 9, A, ... , Z, using . as decimal separator.

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

• – Erik the Outgolfer Aug 17 '17 at 10:49
• for 42, 13, 1 can we have 33 instead of 33.0? – LiefdeWen Aug 17 '17 at 10:54
• @LiefdeWen No, an essential part of the challenge is that the output must have n decimal digits – Luis Mendo Aug 17 '17 at 10:56

# Jelly, 16 bytes

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


Try it online!

Note that singletons are printed as the element in the output.

• Hey, what happened to your picture? – Luis Mendo Aug 17 '17 at 14:31
• @LuisMendo some people cannot render it, since it was connected to Facebook – Leaky Nun Aug 17 '17 at 14:32
• You know you can upload a picture here, right? Those default ones are so impersonal – Luis Mendo Aug 17 '17 at 14:35

## JavaScript (ES8), 8174 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>

Works for x between 1e-6 and 1e21, b from 2 to 36 (exactly as required) and n from 1 to anything from 10 to 48 depending on the base before floating-point errors creep in. Edit: Saved 7 bytes with help from @Birjolaxew. Saved a further 3 bytes with help from @tsh. Previous 74-byte version also worked with negative numbers:

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> • How does one do base conversion with regex?!? – Erik the Outgolfer Aug 17 '17 at 12:22 • @EriktheOutgolfer I'm not, it's just a golfier (hopefully) way of extracting up to n "digits" from a string. – Neil Aug 17 '17 at 12:41 • Then what is the core logic of your function? – Erik the Outgolfer Aug 17 '17 at 12:44 • @EriktheOutgolfer Why, JavaScript's built-in base conversion function of course. (Hint: look at where I use the base parameter.) – Neil Aug 17 '17 at 12:46 • Oh it says .toString(b)...dumb me >_< – Erik the Outgolfer Aug 17 '17 at 12:47 # Python 2, 153149144137135 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  Hadn't noticed I can just return the digits as numbers, so that makes it a lot simpler. Returns two lists of digits, first for the integer part, second for the fractional. Try it online! • In case it helps: I've added a note that you only need to support numbers greater than 1e-6 (and less than 1e15, as before) – Luis Mendo Aug 17 '17 at 14:00 # Perl 6, 25 bytes ->\x,\b,\n{+x .base(b,n)}  Try it ## Expanded: -> \x, \b, \n { +x # make sure it is a Numeric .base( b, n ) # do the base conversion }  Note that the space is so that it is parsed as (+x).base(b,n) not +( x.base(b,n) ). • In case it helps: I've added a note that you only need to support numbers greater than 1e-6 (and less than 1e15, as before) – Luis Mendo Aug 17 '17 at 13:59 # Mathematica, 158 bytes since this challenge allready got a very nice answer in mathematica by @KellyLowder, I tried to produce (with a different approach) the exact results as shown in the test cases ToUpperCase[""<>Insert[StringReplace[ToString@BaseForm[#,p]&/@PadRight[#&@@(d=RealDigits[#,p=#2]),w=(#3+d[[2]])][[;;w]],"\n "<>ToString@p->""],".",d[[2]]+1]]&  input [12944892982609, 29, 9] output PPCGROCKS.000000000 # Ruby, 45 bytes ->x,b,n{(x*b**n).round.to_s(b).insert(~n,?.)}  ### Why? Since b^n in base b is 10^n, we multiply x by that number, and then add the decimal point where it belongs. Try it online! • -1 byte + bugfix by replacing .round with .to_i; this fixes the last digit of the output for ones where it doesn't match the test outputs. -1 more byte by using .insert ~n,?., without parenthesis. – Nnnes Aug 18 '17 at 15:45 # C (gcc), 157 152 bytes Needs 64 bits long int for this to work with larger test cases. -5 bytes thanks to 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;}}  Try it online! edit: a few bytes can be shaved if it's allowed to output two strings separated by a newline separator: ## 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: this submission is not the longest one, yay! • You can use printf(z+r) if it doesn't contain any % characters. (This is code-golf; security and good practices go out the window :P). You could also use puts(z+r) to get a newline for free (saving the puts("") in the second version). – Peter Cordes Aug 18 '17 at 2:37 • Thanks! I forgot about providing a char* directly as a pattern, this indeed saves quite a few bytes :-) I cannot use puts(z+r) in the second version since that would mean each decimal will be printed on a newline – scottinet Aug 18 '17 at 7:13 • Ah, that last part wasn't obvious without an ungolfed version with comments. – Peter Cordes Aug 18 '17 at 13:11 • float is shorter than double, but it seems the question does require a double or string input. – Peter Cordes Aug 18 '17 at 13:15 • No need for that. Some common implementations of C do have 64-bit long, and according to code-golf rules that's all you need for your answer to be valid. (Also, it's common for C and C++ code-golf answers to assume 64-bit long, since that's what Try It Online uses.) I'd suggest rolling back your edit, and just adding a note like "long must be 64-bit for this to support the larger test-cases." – Peter Cordes Aug 18 '17 at 14:46 ## Mathematica 47 Bytes TakeDrop@@r[#,#2,#3+Last@(r=RealDigits)[#,#2]]&  Calling RealDigits twice to first figure out the number of digits to the left of the decimal. • In case it helps: I've added a note that you only need to support numbers greater than 1e-6 (and less than 1e15, as before) – Luis Mendo Aug 17 '17 at 13:57 • I thought the question was just asking for TakeDrop@@RealDigits[##]& but then I realized I had misread things - your solution seems optimal. – Mark S. Aug 17 '17 at 23:53 # SageMath, 68 bytes def f(n,b,k):y=n.str(b).split('.')+[''];return y[0],(y[1]+'0'*k)[:k]  Try it online! • In case it helps: I've added a note that you only need to support numbers greater than 1e-6 (and less than 1e15, as before) – Luis Mendo Aug 17 '17 at 13:59 # 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]))


Try it online!

g converts a number to a list representing that number in a given base

z maps integers to letters (36 = .)

h applies the previous functions to the integer and fractional part of a number.

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


it was particular difficult this question; afther some time in write something, the right results it seems generate using one macro for preserve digits()... it is not golfed too much...results:

(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


the real target is one function that convert to base 2..36 each Float [that has k:=digits()] or each calculated number as %pi or %e or the division of two float/int as in 1./3. ['oo' digits]

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


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


results

(4) -> f(%e,2,10)
(4)  10.1011011111
(5) -> f(%e,3,10)
(5)  2.2011011212
(6) -> f(%e,35,10)
(6)  2.P4VBNEB51S
(7) -> f(1.4,35,10)
(7)  1.DYYYYYYYYY
(8) -> f(%pi,3,8)
(8)  10.01021101
(9) -> f(%pi,5,10)
(9)  3.032322143

 f(4.5,10,5)