24
\$\begingroup\$

Task:

Your task is, when given three inputs:

  • a numerator n
  • a denominator d
  • another integer, x

Create a program/function that finds the xth digit of the number after the decimal place.

Specs:

  • The range of n and d is between 1 and 2^31 - 1, inclusive.
  • The range of x is between 1 and 10,000,000, inclusive.
    • You may choose to use 1-based indexing or 0-based indexing for x. Please state in your answer which one you're using.
  • n may be larger than d.
  • n, d and x are guaranteed to be positive integers (for 1-based index version of x, if you choose to use 0-based indexing for x then x can be 0).
  • You may take inputs in any reasonable way (I.e. any way that is not a standard loophole).

Rules:

  • You must return the exact xth digit, not when rounded - so the 15th digit of 1/6, for example, is not 7, but 6.
  • Your program must work for all x under 10 million, unless your language doesn't support decimals to 10 million places.

Example I/O:

The example input uses 0-based indexing, which means x will go from 0 to 9,999,999. As well as that, the "input" is written as a string with spaces separating the numbers.

1 2 3: 0
5 6 0: 8
5 6 1: 3
1 6 15: 6 (not 7, as it's not rounded)
1 11 2: 0
1 10000 9999999: 0
11 7 1: 7
\$\endgroup\$
20
  • 2
    \$\begingroup\$ This challenge is a subset of this one \$\endgroup\$ Commented Apr 24, 2017 at 13:32
  • 10
    \$\begingroup\$ I also do not think it is a subset of the Pi one, as that one talks about 1 specific irrational number, as this one talks about every rational number \$\endgroup\$ Commented Apr 24, 2017 at 13:38
  • 2
    \$\begingroup\$ Possible duplicate of how to find n'th number in the decimal expansion of a proper fraction? \$\endgroup\$ Commented Apr 24, 2017 at 14:23
  • 1
    \$\begingroup\$ @FelipeNardiBatista Hmmm... I might argue that this should be the opposite way around, as this challenge is more specified with the ranges and stuff (this has happened before, where an older challenge is marked as a dupe of a newer challenge). I'm not sure, though. \$\endgroup\$
    – clismique
    Commented Apr 24, 2017 at 14:24
  • 2
    \$\begingroup\$ It is possible to do the exercise, easily, even in a language that has no bignum... \$\endgroup\$
    – user58988
    Commented Apr 30, 2017 at 5:25

28 Answers 28

14
\$\begingroup\$

Python 2, 25 bytes

Port of my Haskell answer, since Python also supports bignums by default. As there, x is 1-indexed.

lambda n,d,x:n*10**x/d%10

Try it online! (borrowing Keerthana Prabhakaran's wrapper.)

\$\endgroup\$
1
  • \$\begingroup\$ Very nice, I spent a couple of minutes wondering "was it really so easy"? A port to Ruby would be only 21 bytes. \$\endgroup\$
    – G B
    Commented Apr 25, 2017 at 7:49
6
\$\begingroup\$

Mathematica 33 Bytes

RealDigits[#/#2,10,1,-#3][[1,1]]&

1-based indexing.

e.g. 10-millionth digit of Pi right of the decimal point:

%[Pi,1,10^7]
7

takes about 2 seconds on my old machine.

You can try it online at WolframAlpha (click the equal sign)

\$\endgroup\$
0
6
\$\begingroup\$

Haskell, 26 bytes

Works for all test cases. Yay bignums!

(n#d)x takes Integers and returns an Integer. x is 1-indexed.

(n#d)x=n*10^x`div`d`mod`10

Try it online!

\$\endgroup\$
5
\$\begingroup\$

PHP>=7.1, 40 Bytes

<?=bcdiv(($a=$argv)[1],$a[2],$a[3])[-1];

bcdiv

Online Version

\$\endgroup\$
2
  • \$\begingroup\$ I'm getting this error when I run your code: <br /> <b>Notice</b>: Uninitialized string offset: -1 in <b>[...][...]</b> on line <b>6</b><br /> \$\endgroup\$
    – clismique
    Commented Apr 24, 2017 at 13:39
  • \$\begingroup\$ @Qwerp-Derp Sorry you need a PHP Version gte 7.1 and the site will it is the first visit not change it to the higgest version \$\endgroup\$ Commented Apr 24, 2017 at 13:42
4
\$\begingroup\$

Jelly, 7 bytes

⁵*×:ƓDṪ

Try it online!

A function submission (but also works as a full program). Jelly functions can only take two arguments directly; thus I take the digit to return as the left argument, the numerator as the right argument, and the denominator from standard input (in lieu of using a third argument).

People used to Jelly may be aware that a full program can take more than two arguments, but doing so causes you to lose access to the tersest way to write the constant integer 10, which is fairly relevant here. As such, this sort of mixed input feels somewhat like an exploit rather than actual useful golfing; I personally disagree with it, but the rule about allowing this is presently at +40 / -12, so as long as it's in the rules, I may as well exploit it (and pretty much have to to be competitive).

A left argument of 1 refers to the digit immediately after the decimal point (the ".1s digit"), an argument of 2 to the .01s digit, and so on.

Explanation

⁵*×:ƓDṪ
⁵*        10 to the power of {the left argument}
  ×       multiplied by {the right argument}
   :      divided by
    Ɠ                standard input
      Ṫ   take the last
     D                  decimal digit

Jelly has arbitrary-precision arithmetic on integers, so by pre-multiplying by a power of 10, we're effectively moving the digit we want to the units position, where it's much easier to extract.

\$\endgroup\$
4
\$\begingroup\$

sed -r, 93 131 136 bytes

s/$/,/
:d
s/,.+/,/
:
s/(1+)(1*;\1;1*,)1{10}?/\21/
t
s/1*/&&&&&&&&&&/
ta
:a
s/1,/,/
td
s/.+,//

Try it online!

(See output in decimal)

Takes input in unary and outputs in unary, and the program is 1-indexed. Thankfully, this challenge has already prepared me for this one.

The concept is similar, both implement long division. Here, I perform long division x times, where x is the digit after the decimal place that I have to find. After each iteration, I discard the previous decimal places because they are no longer needed.

While doing division, the program is in the format dividend;divisor;x,result.

s/$/,/ adds this comma, the comma is required to separate the result from everything else

Then follows the main program loop

:d label d

  • s/,.+/,/ remove everything after the comma

  • : empty label

    • s/(1+)(1*;\1;1*,)1{10}?/\21/ perform division, adding 1 to the result each iteration, whilst simultaneously removing blocks of 10 continuous 1s in the result
  • t branch to the empty label, in other words, loop until the dividend has been exhausted

  • s/1*/&&&&&&&&&&/ multiply the dividend by 10 to prepare for the next iteration

  • ta branch to label a

  • :a label a, this line and the line above are required to make td work

  • s/1,/,/ subtract 1 from x

td conditional branch to d, this is triggered if there has been a successful substitution since the last conditional branch, since s/1*/&&&&&&&&&&/ is always successful, td will always get triggered, but by introducing branch a, we fix that so that it only depends on the previous substitution

s/.+,// finally, remove everything but the result

\$\endgroup\$
3
\$\begingroup\$

Ruby, 34 33 bytes

->n,d,x{(0..x).map{n=n%d*10};n/d}

Try it online!

\$\endgroup\$
3
\$\begingroup\$

REXX, 76 bytes

(Not very short but thought it would make a change to do one in REXX) Rexx is 1-based by defintion.

arg n d x
numeric digits x+10
y=n/d
parse var y "." +(x) z
say left(z,1,"0")

Explanation:

  1. Read input to the numbers
  2. Guarantee enough significant digits (default is 9)
  3. Calculate
  4. Split. Find the decimal point, count forward "x" characters, take the following characters and put into "z"
  5. Print out first digit. Pad with 0 to be sure.

Merging 3 and 4 actually makes it longer because of the change in syntax:

parse value n/d with "." +x z +1

For non-REXXers: Strings and numbers are totally interchangeable in REXX. They are determined by how you act on them. So you can parse a number using sting functions with no conversion. For example

"27" + "28"

returns 55 and not 2728!

\$\endgroup\$
4
  • \$\begingroup\$ Could you add a link to an interpreter? I'd imagine many users are unfamiliar with this language. \$\endgroup\$
    – user45941
    Commented Apr 25, 2017 at 7:09
  • \$\begingroup\$ tutorialspoint.com/execute_rexx_online.php Only problem is that I couldn't work out how to input values in the interpreter. So, for test purposes, I used assignments to set the values at the start. \$\endgroup\$
    – theblitz
    Commented Apr 25, 2017 at 7:18
  • 1
    \$\begingroup\$ It looks like that interpreter works if you give CLI input like rexx main.rexx 1 2 3. You should mention in your answer that the input is 1-indexed. \$\endgroup\$
    – user45941
    Commented Apr 25, 2017 at 7:21
  • \$\begingroup\$ Didn't notice the input possibility cos I just clicked the execute button at the top. Duh. \$\endgroup\$
    – theblitz
    Commented Apr 25, 2017 at 7:30
2
\$\begingroup\$

Batch, 70 bytes

@set n=%1
@for /l %%x in (0,1,%3)do @set/an=n%%%2*10
@cmd/cset/an/%2
\$\endgroup\$
1
  • \$\begingroup\$ @FelipeNardiBatista Worked for me when I tried it. \$\endgroup\$
    – Neil
    Commented Apr 24, 2017 at 15:16
2
\$\begingroup\$

Assembly Intel x86 cpu language, 50 bytes

00000940  53                push ebx
00000941  8B5C240C          mov ebx,[esp+0xc]
00000945  8B4C2410          mov ecx,[esp+0x10]
00000949  31C0              xor eax,eax
0000094B  48                dec eax
0000094C  81C102000000      add ecx,0x2
00000952  721A              jc 0x96e
00000954  81FB00000000      cmp ebx,0x0
0000095A  7412              jz 0x96e
0000095C  8B442408          mov eax,[esp+0x8]
00000960  31D2              xor edx,edx
00000962  F7F3              div ebx
00000964  49                dec ecx
00000965  7407              jz 0x96e
00000967  8D0492            lea eax,[edx+edx*4]
0000096A  01C0              add eax,eax
0000096C  EBF2              jmp short 0x960
0000096E  5B                pop ebx
0000096F  C20C00            ret 0xc

traslation in nasm

; u32 __stdcall rdiv(u32 a, u32  b, u32 c)
; 8a, 12b, 16c
      align   4
rdiv:                   ; c<0xFFFFFFFE and b!=0
      push    ebx       ; something as for(;a=10*(a%b),c--;);return a/b
      mov     ebx,  dword[esp+  12]
      mov     ecx,  dword[esp+  16]
      xor     eax,  eax
      dec     eax
      add     ecx,  2
      jc      .z
      cmp     ebx,  0
      je      .z            
      mov     eax,  dword[esp+  8]
.1:   xor     edx,  edx
      div     ebx
      dec     ecx
      jz      .z
      lea     eax,  [edx+edx*4]
      add     eax,  eax
      jmp     short  .1     ; a=5*a;a+=a=>a=10*a
.z:       
      pop     ebx
      ret     12

For parameter 'c' the range begin from 0; it would be 0..0xfffffffd. If parameters b=0 or c out of range 0..0xfffffffd it would return -1

\$\endgroup\$
1
\$\begingroup\$

Lua, 42 bytes

function a(n,x,d)
print((n*10^x/d)%10)
end
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Hello, and welcome to PPCG! This is a great first answer! \$\endgroup\$ Commented Apr 25, 2017 at 18:01
1
\$\begingroup\$

C, 49 43 bytes

f(a,b,i){for(;a=10*(a%b),i--;);return a/b;}

'i' argument is 0-indexing. Test code and result

main()
{int i;
 for(i=0;i<20;++i)
     printf("%u", f(12,11,i));

 printf("\nf(1,2,3)=%d\n",f(1,2,3));
 printf("f(5,6,0)=%d\n",f(5,6,0));
 printf("f(5,6,1)=%d\n",f(5,6,1));
 printf("f(1,6,15)=%d\n",f(1,6,15));
 printf("f(1,11,2)=%d\n",f(1,11,2));
 printf("f(1,10000,9999999)=%d\n",f(1,10000,9999999));
 printf("f(11,7,1)=%d\n",f(11,7,1));
}

f(1,2,3)=0
f(5,6,0)=8
f(5,6,1)=3
f(1,6,15)=6
f(1,11,2)=0
f(1,10000,9999999)=0
f(11,7,1)=7 
\$\endgroup\$
1
\$\begingroup\$

Java 7, 146 139 137 133 128 122 Bytes

-3 bytes thanks to Erik the Outgolfer, I totally forgot imports didn't have to be on their own line

-4 bytes thanks to Qwerp-Derp for moving n%d to the constructor

-6 bytes thanks Kevin Cruijssen for removing the toString()

I hope this is how the byte count is done for java functions with imports

import java.math.*;char a(int n,int d,int x){return (new BigDecimal(n%d).divide(new BigDecimal(d),x+1,1)+"").charAt(x+2);}

Uses Java's BigDecimal class to get exact representation of the decimal expansion. Note it's not the fastest running code ever but it does eventually produce the correct output for all test cases. Ungolfed code:

import java.math.*;
char a(int n, int d, int x){
    BigDecimal num = new BigDecimal(n%d); // reduce improper fractions
    BigDecimal div = new BigDecimal(d);
    BigDecimal dec = num.divide(div, x+1, 1); // precision of x + 1, round down
    return (dec+"").charAt(x+2); //xth char after decimal
}

Try it online!

\$\endgroup\$
7
  • \$\begingroup\$ The spaces after the commas and the newline after the semicolon can be removed I think. \$\endgroup\$ Commented Apr 24, 2017 at 16:00
  • \$\begingroup\$ I count 137 bytes \$\endgroup\$
    – user41805
    Commented Apr 25, 2017 at 8:03
  • \$\begingroup\$ Must have miscounted thanks \$\endgroup\$
    – PunPun1000
    Commented Apr 25, 2017 at 11:07
  • \$\begingroup\$ Can't you just replace BigDecimal(n) with BigDecimal(n%d), and get rid of the n=n%d? \$\endgroup\$
    – clismique
    Commented Apr 25, 2017 at 13:42
  • \$\begingroup\$ You can remove the .toString() and use +"" instead (with two additional parenthesis). \$\endgroup\$ Commented May 4, 2017 at 15:23
1
\$\begingroup\$

Clojure, 39 bytes

#(mod(int(/(*(Math/pow 10 %3)%)%2))10))

anonymous function with arguments n,d,x where x uses one based indexing.

\$\endgroup\$
1
\$\begingroup\$

F# (.NET Core), 30 bytes

let f n d x=n*pown 10I x/d%10I

Try it online!

(use 1-based indexing)

\$\endgroup\$
2
  • \$\begingroup\$ I count 33 bytes. I would also suggest to add a Try it Online! link. \$\endgroup\$
    – wastl
    Commented May 19, 2018 at 20:01
  • \$\begingroup\$ I had the wrong function in my clipboard. Thanks. \$\endgroup\$ Commented May 19, 2018 at 20:06
1
\$\begingroup\$

Groovy, 30 bytes

{n,d,x->(n*10**x/d as int)%10}

x uses 1 based indexing.

Explanation:

{n,d,x->    // closure with three arguments, n, d, x
 n*10**x    // multiply n with 10 to the power of x
 /d         // divide by d
 as int     // convert from BigDecimal to int
 )%10       // modulo 10 to get the answer
}
\$\endgroup\$
1
\$\begingroup\$

Vyxal, 6 bytes

/$›ḞṪt

Try it Online!

I do like the Sympy wrappers vyxal now has. Takes denominator, numerator then index.

Explained

/$›ḞṪt
/      # divide the numerator by the denominator. This is fine because vyxal stores floats as Rationals internally. 
 $     # place the index at the top of the stack 
  ›Ḟ   # Sympy.evalf(fraction, n=index+1). This avoids rounding issues
    Ṫt # get the second last item  
\$\endgroup\$
1
\$\begingroup\$

Nibbles, 4 bytes (8 nibbles)

/\`p/*^~

Input is x, n, d. Uses 1-based indexing.

     *      # multiply
      ^~    #   10 to the power of
            #     (implicitly) arg1
            # by
            #   (implicitly) arg2
    /       # and divide this by (implicitly) arg3
  `p        # print the number as a string
 \          # reverse it
/           # and get the first element 
            # (by folding across it, each time
            # returning the left-hand of each pair)

enter image description here

\$\endgroup\$
1
\$\begingroup\$

Pyt, 7 bytes

ᴇ*⇹/1ᴇ%

Try it online!

input is x,n,d

ᴇ         raises 10 to the x
 *        multiplies by n
  ⇹/      divides by d
    1ᴇ%   modulo 10; implicit print
\$\endgroup\$
0
\$\begingroup\$

Python 2, 50,44,40, 36 bytes

lambda n,d,x:(`n*1./d%1`+'0'*x)[x+2]

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ does not work for 1,7,10000000 \$\endgroup\$ Commented Apr 25, 2017 at 10:37
0
\$\begingroup\$

Ruby, 39 bytes

->n,m,o{(n*1.0/m).to_s.split(?.)[1][o]}
\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 34 bytes

(n,d,x)=>`${n/d}`.split`.`[1][x]|0

x is 0-based

f=
(n,d,x)=>`${n/d}`.split`.`[1][x]|0

console.log(f(1,2,3))
console.log(f(5,6,0))
console.log(f(5,6,1))
console.log(f(1,6,15))
console.log(f(1,11,2))
console.log(f(1,10000,10000000))
console.log(f(11,7,1))
console.log(f(2000,7,0))

\$\endgroup\$
1
  • \$\begingroup\$ Unfortunately, like my solution, this will fail with long decimals; try f(1,7,10000000), for example. \$\endgroup\$
    – Shaggy
    Commented Apr 25, 2017 at 9:15
0
\$\begingroup\$

Python 2, 32 bytes

Uses 0-indexing

lambda n,d,x:int(10**-~x*n/d)%10

Try it online!

Edit:

Rolled back to original solution as seen in Ørjan Johansen's answer that it works, but I won't golf it any further

\$\endgroup\$
5
  • 2
    \$\begingroup\$ If it isn't valid then it should be deleted. \$\endgroup\$ Commented Apr 24, 2017 at 13:48
  • \$\begingroup\$ as most of the answers so far \$\endgroup\$ Commented Apr 24, 2017 at 14:34
  • \$\begingroup\$ @EriktheOutgolfer fixed it... \$\endgroup\$ Commented Apr 24, 2017 at 14:49
  • \$\begingroup\$ Do you use 1-indexing? \$\endgroup\$ Commented Apr 24, 2017 at 15:00
  • \$\begingroup\$ Try it online! \$\endgroup\$ Commented Apr 25, 2017 at 1:10
0
\$\begingroup\$

Groovy, 55 bytes

{n,d,x->z='0'*x;Eval.me("$n.$z/$d.$z").toString()[x-1]}

Explained using 1,11,2:

{
    n,d,x->          // I've already lost to Jelly by the end of this line.
    z='0'*x;         // Set z equal to 2 0's.
    Eval.me          // Evaluate as groovy code...
    ("$n.$z/$d.$z")  // 1.00g/11.00g (Automatically set precision using # 0s).
   .toString()[x-1]  // Get 2nd digit of division.
}
\$\endgroup\$
0
\$\begingroup\$

Axiom, 71 61 76 bytes

f(a:NNI,b:PI,n:NNI):NNI==(repeat(a:=10*(a rem b);n=0=>break;n:=n-1);a quo b)

n is 0-indexing [0..M]. Test code and result

(19) ->    f(1,2,3)=0
   (19)  0= 0
(20) ->     f(5,6,0)=8
   (20)  8= 8
(21) ->     f(5,6,1)=3
   (21)  3= 3
(22) ->     f(1,6,15)=6
   (22)  6= 6
(23) ->     f(1,11,2)=0
   (23)  0= 0
(24) ->     f(1,10000,9999999)=0
   (24)  0= 0
(25) ->     f(11,7,1)=7
   (25)  7= 7
\$\endgroup\$
0
\$\begingroup\$

Husk, 9 bytes

→d÷⁰*²!İ⁰

Try it online!

\$\endgroup\$
0
\$\begingroup\$

JavaScript (Node.js), 23 bytes

(a,b,i)=>a*10n**i/b%10n

Try it online!


JavaScript (Node.js), 43 bytes, port

(a,b,i)=>eval(`for(;a=10*(a%b),i--;)a/b|0`)

Try it online!

JavaScript (Node.js), 51 bytes

(n,d,x)=>[...Array(x)].map(_=>[n*=10,u=n/d,n%=d])|u

Try it online!

use Array rather than recursive to avoid stackoverflow

\$\endgroup\$
0
\$\begingroup\$

Thunno, \$ 9 \log_{256}(96) \approx \$ 7.41 bytes

10@*s10%,

Attempt This Online! Takes x then n then d.

Port of Ørjan Johansen's Python answer

Explanation:

10@*s10%,  # Implicit input, x then n then d
10@        # 10**x
   *       # *n
    s      # Swap so d is on top
     10%   # d%10
        ,  # Integer divide
           # Implicit output
\$\endgroup\$

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