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


  • 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).

Additional rules

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
  • \$\begingroup\$ Let us continue this discussion in chat. \$\endgroup\$ – Erik the Outgolfer Aug 17 '17 at 10:49
  • \$\begingroup\$ for 42, 13, 1 can we have 33 instead of 33.0? \$\endgroup\$ – LiefdeWen Aug 17 '17 at 10:54
  • \$\begingroup\$ @LiefdeWen No, an essential part of the challenge is that the output must have n decimal digits \$\endgroup\$ – Luis Mendo Aug 17 '17 at 10:56

12 Answers 12


Jelly, 16 bytes


Try it online!

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

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

JavaScript (ES8), 81 74 71 bytes

<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:

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

  • 1
    \$\begingroup\$ How does one do base conversion with regex?!? \$\endgroup\$ – Erik the Outgolfer Aug 17 '17 at 12:22
  • 1
    \$\begingroup\$ @EriktheOutgolfer I'm not, it's just a golfier (hopefully) way of extracting up to n "digits" from a string. \$\endgroup\$ – Neil Aug 17 '17 at 12:41
  • \$\begingroup\$ Then what is the core logic of your function? \$\endgroup\$ – Erik the Outgolfer Aug 17 '17 at 12:44
  • \$\begingroup\$ @EriktheOutgolfer Why, JavaScript's built-in base conversion function of course. (Hint: look at where I use the base parameter.) \$\endgroup\$ – Neil Aug 17 '17 at 12:46
  • \$\begingroup\$ Oh it says .toString(b)...dumb me >_< \$\endgroup\$ – Erik the Outgolfer Aug 17 '17 at 12:47

Python 2, 153 149 144 137 135 109 bytes

def f(x,b,m):
 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!

  • \$\begingroup\$ 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) \$\endgroup\$ – Luis Mendo Aug 17 '17 at 14:00

Perl 6, 25 bytes

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

Try it


-> \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) ).

  • \$\begingroup\$ 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) \$\endgroup\$ – 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]]&


[12944892982609, 29, 9]




Ruby, 45 bytes



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!

  • \$\begingroup\$ -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. \$\endgroup\$ – 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!

  • 2
    \$\begingroup\$ 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). \$\endgroup\$ – Peter Cordes Aug 18 '17 at 2:37
  • \$\begingroup\$ 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 \$\endgroup\$ – scottinet Aug 18 '17 at 7:13
  • \$\begingroup\$ Ah, that last part wasn't obvious without an ungolfed version with comments. \$\endgroup\$ – Peter Cordes Aug 18 '17 at 13:11
  • \$\begingroup\$ float is shorter than double, but it seems the question does require a double or string input. \$\endgroup\$ – Peter Cordes Aug 18 '17 at 13:15
  • 1
    \$\begingroup\$ 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." \$\endgroup\$ – Peter Cordes Aug 18 '17 at 14:46

Mathematica 47 Bytes


Calling RealDigits twice to first figure out the number of digits to the left of the decimal.

  • \$\begingroup\$ 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) \$\endgroup\$ – Luis Mendo Aug 17 '17 at 13:57
  • 1
    \$\begingroup\$ I thought the question was just asking for TakeDrop@@RealDigits[##]& but then I realized I had misread things - your solution seems optimal. \$\endgroup\$ – 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!

  • \$\begingroup\$ 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) \$\endgroup\$ – Luis Mendo Aug 17 '17 at 13:59

Haskell, 188 bytes

g 0 _=[]
g n p=g(div n p)p++[mod n p]
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)
F(x)==>for i in 1..#x repeat z:=concat(z,x.i)
  z:="";b<2 or b>36 or a<0=>z
  ip:=g(a);    fp:=g((a-ip)*b^n)
  for i in 1..cnt repeat fpb:=cons(c.1,fpb)

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


(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

It has a little problem for final zero example


Would return '4.5' and not '4.50000'


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.